鸟哥的Linux私房菜(基础学习篇第四版)学习笔记


目录

  • 零、第零章-计算机概论
    • 0.1 电脑:辅助人脑的好工具
      • 0.1.1 电脑硬件的五大单元-pg4
      • 0.1.6 电脑上面常用的计量单位-pg8
    • 0.2 个人电脑架构与相关设备组件
      • 0.2.1 执行脑袋运算与判断的CPU-pg11
      • 0.2.2 内存-pg14
      • 0.2.3 显卡-pg16
      • 0.2.4 硬盘与存储设备-pg17
      • 0.2.6 主板-pg21
      • 0.2.8 选购须知-pg22
    • 0.4 软件程序运行
      • 0.4.2 操作系统-pg26
  • 壹、第一章-Linux是什么与如何学习
    • 1.1 Linux是什么
      • 1.1.1 Linux是什么?操作系统/应用程序?-pg34
  • 贰、第二章-主机规划与磁盘分区
    • 2.1 Linux与硬件的搭配
      • 2.1.3 各硬件设备在Linux中的文件名-pg67
    • 2.2 磁盘分区
      • 2.2.4 Linux安装模式下,磁盘分区的选择(极重要)-pg79
  • 叁、第三章-安装CentOS 7.x
  • 肆、第四章-首次登录与在线求助
    • 4.2 命令行模式下命令的执行
      • 4.2.1 开始执行命令-pg127
      • 4.2.2 基础命令的操作-pg130
      • 4.2.3 重要的几个热键[Tab]、[Ctrl]-c、[Ctrl]-d-pg132
    • 4.3 Linux系统的在线求助man page与info page
      • 4.3.1 命令的 --help 求助说明-pg134
      • 4.3.2 man page-pg135
      • 4.3.3 info page-pg139
    • 4.4 超简单的文本编辑器:nano-pg142
    • 4.5 正确的关机方式-pg143
  • 伍、第五章-Linux的文件权限与目录配置
    • 5.2 Linux文件权限概念
      • 5.2.1 Linux文件属性-pg152
      • 5.2.2 如何修改文件属性与权限-pg156
      • 5.2.4 Linux文件种类与扩展名-pg163
    • 5.3 Linux目录配置
      • 5.3.1 Linux目录配置的依据————FHS-pg165
      • 5.3.2 目录树(directory tree)-pg169
      • 5.3.3 绝对路径与相对路径-pg170
  • 陆、第六章-Linux文件与目录管理
    • 6.1 目录与路径
      • 6.1.1 绝对路径与相对路径-pg176
      • 6.1.2 目录的相关操作-pg176
      • 6.1.3 关于执行文件路径的变量:$PATH-pg179
    • 6.2 文件与目录管理
      • 6.2.1 文件与目录查看:ls-pg181
      • 6.2.2 复制、删除与移动:cp、rm、mv-pg183
      • 6.2.3 获取路径的文件名与目录名称-pg186
    • 6.3 文件内容查看
      • 6.3.1 直接查看文件内容-pg187
      • 6.3.2 可翻页查看-pg188
      • 6.3.3 数据截取-pg190
      • 6.3.4 非纯文本文件:od-pg191
      • 6.3.5 修改文件时间或创建新文件:touch-pg192
    • 6.4 文件与目录的默认权限与隐藏权限
      • 6.4.1 文件默认权限:umask-pg195
      • 6.4.2 文件隐藏属性-pg196
      • 6.4.3 文件特殊权限:SUID、SGID、SBIT-pg198
      • 6.4.4 观察文件类型:file-pg200
    • 6.5 命令与文件的查找
      • 6.5.1 脚本文件的查找-pg201
      • 6.5.2 文件的查找-pg201
    • 7.1 认识Linux文件系统
      • 7.1.1 磁盘组成与分区的复习-pg210
      • 7.1.2 文件系统特性-pg211
      • 7.1.3 Linux的ext2文件系统(inode)-pg212
      • 7.1.4 与目录树的关系-pg217
      • 7.1.5 ext2/ext3/ext4文件的存取与日志式文件系统的功能-pg219
      • 7.1.6 Linux文件系统的运行-pg220
      • 7.1.7 挂载点的意义(mount point)-pg221
      • 7.1.8 其他Linux支持的文件系统与VFS-pg221
      • 7.1.9 XFS文件系统简介-pg222
    • 7.2 文件系统的简单操作
      • 7.2.1 磁盘与目录的容量-pg224
      • 7.2.2 硬链接与符号链接-pg227
    • 7.3 磁盘的分区、格式化、检验与挂载
      • 7.3.1 观察磁盘分区状态-pg232
      • 7.3.2 磁盘分区:gdisk/fdisk-pg233
      • 7.3.3 磁盘格式化(创建文件系统)-pg238
      • 7.3.4 文件系统检验-pg241
      • 7.3.5 文件系统挂载与卸载-pg243
      • 7.3.6 磁盘/文件系统参数自定义-pg246
    • 7.4 设置启动挂载
      • 7.4.1 启动挂载/etc/fstab及/etc/mtab-pg248
      • 7.4.2 特殊设备loop挂载(镜像文件不刻录就挂载使用)-pg251
    • 7.5 内存交换分区(swap)之创建
      • 7.5.1 使用物理分区创建内存交换分区-pg253
      • 7.5.2 使用文件创建内存交换文件-pg254
    • 7.6 文件系统的特殊观察与操作
      • 7.6.2 利用GNU的parted进行分区操作(可选)-pg256
    • 8.1 压缩文件的用途与技术-pg262
    • 8.2 Linux系统常见的压缩命令
      • 8.2.1 gzip,zcat/zmore/zless/zgrep-pg263
      • 8.2.2 bzip2,bzcat/bzmore/bzless/bzgrep-pg265
      • 8.2.3 xz,xzcat/xzmore/xzless/xzgrep-pg265
    • 8.3 打包命令:tar-pg266
    • 8.4 XFS文件系统的备份与还原
      • 8.4.1 XFS文件系统备份xfsdump-pg272
      • 8.4.2 XFS文件系统还原xfsrestore-pg275
    • 8.5 光盘写入工具
      • 8.5.1 mkisofs:建立镜像文件-pg277
      • 8.5.2 cdrecord:光盘刻录工具-pg280
    • 8.6 其他常见的压缩与备份工具
      • 8.6.1 dd-pg282
      • 8.6.2 cpio-pg284
  • 玖、第九章-vim程序编辑器
    • 9.1 vi与vim
    • 9.2 vi的使用
      • 9.2.1 简易执行范例-pg292
      • 9.2.2 按键说明-pg293
    • 9.2 vi的使用-pg299
    • 9.2 vim的额外功能
      • 9.3.1 可视区块(Visual Block)-pg300
      • 9.3.2 多文件编辑-pg301
      • 9.3.3 多窗口功能-pg302
      • 9.3.4 vim的关键词补充功能-pg303
      • 9.3.5 vim环境设置与记录:~/.vimrc、~/.viminfo-pg304
      • 9.3.6 vim常用命令示意图-pg305
    • 9.4 其他vim使用注意事项
      • 9.4.1 中文编码的问题-pg306
      • 9.4.2 DOS与Linux的换行符-pg306
      • 9.4.3 语系编码转换-pg307
  • 拾、第十章-认识与学习BASH
    • 10.1 认识BASH这个shell
      • 10.1.1 硬件、内核与Shell-pg311
      • 10.1.4 Bash shell的功能-pg314
      • 10.1.5 查询命令是否为Bash shell的内置命令:type-pg315
      • 10.1.6 命令的执行与快速编辑按钮-pg316
    • 10.2 Shell的变量功能
      • 10.2.1 什么是变量-pg318
      • 10.2.2 变量的使用与设置:echo、变量设置规则、unset-pg318
      • 10.2.3 环境变量的功能-pg322
      • 10.2.6 变量键盘读取、数组与声明:read、array、declare-pg327
      • 10.2.7 与文件系统及程序的限制关系:ulimit-pg329
      • 10.2.8 变量内容的删除、取代与替换(可选)-pg330
    • 10.3 命名别名与历史命令
      • 10.3.1 命令别名设置:alias、unalias-pg334
      • 10.3.2 历史命令:history-pg335
    • 10.4 Bash shell的操作环境
      • 10.4.1 路径与命令查找顺序-pg337
      • 10.4.3 bash的环境配置环节-pg338
      • 10.4.4 终端的环境设置:stty、set-pg342
      • 10.4.5 通配符与特殊符号-pg344
    • 10.5 数据流重定向
      • 10.5.1 什么是数据流重定向-pg345
      • 10.5.2 命令执行的判断根据:;、&&、||-pg348
    • 10.6 管道命令(pipe)
      • 10.6.1 选取命令:cut、grep-pg351
      • 10.6.2 排序命令:sort、wc、uniq-pg353
      • 10.6.3 双向重定向:tee-pg354
      • 10.6.4 字符转换命令:tr、col、jion、paste、expand-pg354
      • 10.6.5 划分命令:split-pg357
      • 10.6.6 参数代换:xargs-pg358
      • 10.6.7 关于减号【-】的用途-pg359
  • 拾壹、第十一章-正则表达式与文件格式化处理
    • 11.1 开始之前-pg363
    • 11.2 基础正则表达式
      • 11.2.1 语系对正则表达式的影响-pg365
      • 11.2.2 grep的一些高级选项-pg365
      • 11.2.3 基础正则表达式练习-pg366
      • 11.2.4 基础正则表达式字符集合(characters)-pg371
      • 11.2.5 sed工具-pg373
    • 11.3 扩展正则表达式-pg376
    • 11.4 文件的格式化与相关处理
      • 11.4.1 格式化打印:printf-pg377
      • 11.4.2 awk:好用的数据处理工具-pg379
      • 11.4.3 文件比对工具-pg381
      • 11.4.4 文件打印设置:pr-pg384
  • 拾贰、第十二章-学习shell脚本(很重要)
    • 12.1 什么是shell脚本
      • 12.1.1 为什么要学习shell脚本-pg388
      • 12.1.2 第一个脚本的编写与执行-pg389
      • 12.1.3 建立shell脚本的良好编写习惯-pg391
    • 12.2 简单的shell脚本练习
      • 12.2.2 脚本的执行方式差异(source、sh script、 ./script)-pg394
    • 12.3 善用判断式
      • 12.3.1 利用test命令的测试功能-pg395
      • 12.3.2 利用判断符号-pg397
      • 12.3.3 shell脚本的默认变量-pg399
    • 12.4 条件判断式
      • 12.4.1 利用if...then-pg401
      • 12.4.2 利用case...esac-pg405
      • 12.4.3 利用利用function功能-pg406
    • 12.5 循环(loop)
      • 12.5.1 while do done、until do done(不定循环)-pg408
      • 12.5.2 for...do...done(固定循环)-pg409
      • 12.5.3 for...do...done的数值处理-pg411
    • 12.6 shell脚本的跟踪与调试-pg413
  • 拾叁、第十三章-Linux账户管理与ACL权限设置
    • 13.1 Linux的账号与用户组
      • 13.1.1 用户标识符:UID与GID-pg418
      • 13.1.2 用户账号-pg419
      • 13.1.3 关于用户组:有效与初始用户组,groups,newgr-pg423
    • 13.2 账号管理
      • 13.2.1 新增与删除用户:useradd、相关配置文件、passwd、usermod、userdel-pg418


第一部分 Linux的规则与安装


零、第零章-计算机概论

写在正文前,为非计算机专业的人提供一个提前的知识整理机会。


0.1 电脑:辅助人脑的好工具

0.1.1 电脑硬件的五大单元-pg4

电脑的五大组成单元:输入单元输出单元、CPU内部的控制单元算术逻辑单元内存

0.1.6 电脑上面常用的计量单位-pg8

0/1这个二进制的单位我们称为bit,亦称比特)。

但是位实在是太小了,所以在存储数据时,每份简单的数据都会使用到8个位的大小来记录,因此定义出字节Byte)这个单位,它们的关系对应如下:

1 字节 = 8 位


0.2 个人电脑架构与相关设备组件

0.2.1 执行脑袋运算与判断的CPU-pg11

CPU的频率速度 = 外频 * 倍频

在早期的CPU设计中:
外频是指CPU与外部部件进行数据传输时的速度;
倍频是指CPU内部用来加速工作性能的一个倍数。

0.2.2 内存-pg14

BIOS
BIOS(Basic Input Output System)是一个程序,这个程序是写死到主板上面的一个存储芯片中,这个存储芯片在没有通电时也能够记录数据,这就是只读存储器(Read Only Memory,ROM)。

0.2.3 显卡-pg16

补一个接口知识:

  • D-Sub(VGA接口):为较早之前的连接接口,主要为15针的接口,为模拟信号的传输所使用。当初设计是针对传统的CRT显示器而来,主要的规格标准有640×350px@70Hz、1280×1024px@85Hz及2048×1536@85Hz等。
  • DIV:共有四种以上的接口,不过市面上比较常见的仅为提供数字信号的DVI-D,以及整合数字和模拟信号的DVI-I两种。DVI常见于液晶屏幕的连接,标准规格主要有1920×1200px@60Hz、2560×1600px@60Hz等。
  • HDMI:相对于D-Sub与DVI仅能传输影像数据,HDMI可以同时传输影像与声音,因此被广泛地使用于电视屏幕中,电视屏幕目前也经常都会支持HDMI格式。
  • Display:与HDMI相似,可以同时传输声音和影像,不过这种接口目前在市面上还是比较少有屏幕的支持。

0.2.4 硬盘与存储设备-pg17

扇区(sector):磁盘的最小物理存储单位。

磁道(track):同一个同心圆的扇区组合成的圆。

柱面(cylinder):所有碟片上面的用一个磁道可以组合成所谓的柱面。

机械硬盘(Hard Disk Drive,HDD):需要驱动马达去转动碟片。先知道数据在哪个扇区上面,然后命令马达开始转,再让磁头去读取正确的数据。缺点是:磁盘读取延迟。

固态硬盘(Solid State Drive,SSD):最大好处是没有马达不需要转动,而是通过闪存直接读写的特性,因此除了没数据延迟且快速之外,还很省电。

0.2.6 主板-pg21

南北桥:
(1)北桥:负责连接速度较快的CPU、内存与显卡等组件;现在大多数北桥整合到CPU中了。
(2)南桥:负责连接速度较慢的设备接口,包括硬盘、USB设备、网卡等。

扩展卡数据需要先进入南桥跟大家抢带宽,之后要传向CPU时,还得要通过CPU与南桥的通信管道,那条管道称为DMI2.0总线

扩展卡装在哪个插槽上面,对性能而言也是影响很大的。所以插卡时,请详情阅读主板上面的逻辑图例,尤其是CPU与南桥通信的带宽方面,特别重要。

CMOS主要的功能为记录主板上面的重要参数,包括系统时间、CPU电压与频率、各项设备的I/O地址与IRQ等,由于这些数据的记录需要用电,因此主板上面才有电池。

BIOS是写入到主板上某一块flash或EEPROM的程序,它可以在计算机启动的时候执行,以加载CMOS当中的参数,并尝试调用存储设备中的引导程序,进一步进入操作系统当中。

0.2.8 选购须知-pg22

**Tips:**如果公司需要一台服务器的话,建议不要自行组装,买品牌电脑的服务器比较好。速度的快慢与整体系统的最慢的那个设备有关。


0.4 软件程序运行

0.4.2 操作系统-pg26

API:应用程序编程接口(Application Programming Interface,API)。


壹、第一章-Linux是什么与如何学习


1.1 Linux是什么

1.1.1 Linux是什么?操作系统/应用程序?-pg34

Linux是具有“可移植性”的。


贰、第二章-主机规划与磁盘分区


2.1 Linux与硬件的搭配

2.1.3 各硬件设备在Linux中的文件名-pg67

几乎所有的硬件设备文件都在/dev这个目录内,比如/dev/sda、/dev/sr0等。


2.2 磁盘分区

2.2.4 Linux安装模式下,磁盘分区的选择(极重要)-pg79

Linux内的所有数据都是以文件的形式来呈现,整个Linux系统最重要的地方就是在于目录树结构。

目录树结构(directory tree)就是以根目录为主,然后向下呈现为分支状的目录结构的一种文件架构。

整个目录树结构最重要的就是那个根目录(root directory)。根目录的表示方法为一条斜线**“/”**,所有的文件都与目录树有关。

挂载(mount):所谓挂载就是利用一个目录当成进入点,将磁盘分区的数据放置在该目录下;也就是说进入该目录就可以读取该分区的意思。


叁、第三章-安装CentOS 7.x

本书采用的是CentOS 7.x,我用的虚拟机是Ubuntu,仁者见仁吧


肆、第四章-首次登录与在线求助


4.2 命令行模式下命令的执行

4.2.1 开始执行命令-pg127

**-ls**命令

-ls //用于显示指定工作目录下之内容(列出目前工作目录所含之文件及子目录)

4.2.2 基础命令的操作-pg130

简单好用的计算机:bc

进入:直接输入bc
退出:输入quit

  • 加法 +
  • 减法 -
  • 乘法 *
  • 除法 /
  • 指数 ^
  • 余数 %

4.2.3 重要的几个热键[Tab]、[Ctrl]-c、[Ctrl]-d-pg132

  • [Tab]

    • [Tab]接在一串命令的第一个字段后面,表示【命令补全】
    • [Tab]接在一串命令的第二个字段后面,表示【文件补齐】
  • [Ctrl]-c

注意,Linux下的[Ctrl]-c不是代表复制,而是用来中断正在运行的命令。

  • [Ctrl]-d

[Ctrl]-d表示键盘输入结束,相当于exit。


4.3 Linux系统的在线求助man page与info page

4.3.1 命令的 --help 求助说明-pg134

使用 –help 可以将该命令的用法做一个大致的了解,类似于说明手册,查阅命令的使用方法。

4.3.2 man page-pg135

其中,man 是manual(操作说明)的简写。
以 date 命令为例,执行man date,可以清楚的看到date命令的说明。

进入man命令的功能后,按下【空格键】往下翻页,可以按下【q】按键来离开man的环境。

【DATE(1)】代表的是:“一般用户可以使用的命令”的意思。表格如下:

代号代表内容
1用户在shell环境中可以操作的或可执行文件
2系统内核可调用的函数与工具等
3一些常用的函数(function)与函数库(library),大部分为C的函数库(libc)
4设备文件的说明,通常在/dev下的文件
5配置文件或是某些文件的格式
6游戏(games)
7惯例与协议等,例如Linux文件系统、网络协议、ASCII代码等的说明
8系统管理员可用的管理命令
9跟内核有关的文件

其他命令代号:

代号内容说明
NAME简短的命令、数据名称说明
SYNOPSIS简短的命令语法(syntax)简介
DESCRIPTION较为完整的说明,这部分最好仔细看看
OPTIONS针对SYNOPSIS部分中,有列举的所有可用的选项说明
COMMANDS当这个程序(软件)在执行的
FILES这个程序或数据所使用或参考或链接到的某些文件
SEE ALSO可以参考跟这个命令或数据有相关的其他说明
EXAMPLE一些可以参考的范例

查阅顺序:

  1. 先查看NAME的部分,约略看一下这个数据的意思;
  2. 再详细看一下DESCRIPTION,这个部分会提到很多相关的数据与使用时机,从这个地方可以学到很多小细节;
  3. 而如果这个命令已经很熟悉了,那么主要查询关于OPTIONS的部分就可以了。可以知道每个选项的意义,这样就可以执行比较详细的命令内容;
  4. 最后,再看一下,跟这个数据有关的还有哪些东西可以使用;
  5. 某些说明还会列举有关的文件(FILES部分)来提供参考。

man page内部常用的按键:

按键进行工作
空格键向下翻一页
[Page Down]向下翻一页
[Page Up]向上翻一页
[Home]去到第一页
[End]去到最后一页
/string向【下】查找string这个字符串,如果要查找vbird的话,就输入/vbird
?string向【上】查找string这个字符串
n,N利用/或?来查找字符串时,可以用n来继续下一个查找(不论是/或?),可以利用N来进行【反向】查找(向上查找)
q结束这次的man page

man -f man:取得更多的与man相关的信息。

man -k man:利用关键词将说明文件里面只要含有man那个字眼就将它取出。

4.3.3 info page-pg139

info page:和man page类似,与man page一口气输出一堆信息不同的是,info page则是将文件数据拆成一个一个的段落,每个段落用自己的页面来编写,并且在各个页面中还有类似网页的超链接来跳到各个不同的页面中,每个独立的页面也被称为一个**节点**(node)。所以,你可以将info page想成是命令行模式的网页显示数据。

按键进行工作
空格键向下翻一页
[Page Down]向下翻一页
[Page Up]向上翻一页
[Tab]在节点之间移动,有节点的地方,通常会以*显示
[Enter]当光标在节点上面时,按下Enter可以进入该节点
b移动光标到该info界面当中的第一处
e移动光标到该info界面当中的最后一个节点一处
n前往下一个节点处
p前往上一个节点处
u向上移动一层
s(/)在info page当中进行查找
h,?显示帮助选项
q结束这次的info page

4.4 超简单的文本编辑器:nano-pg142

打开一个名为text.txt的文件: nano text.txt

其中,那个指数符号(^)代表的是键盘的[Ctrl]按键;

M代表的是键盘的[Alt]按键。


4.5 正确的关机方式-pg143

正确的关机命令使用

  • 将数据同步写入键盘中的命令:sync
  • 常用的关机命令;shutdown
  • 重新启动,关机:reboot、halt、poweroff

一般在重新启动时,都会执行如下的命令:

sync; sync; sync; reboot

第二部分 Linux文件、目录与磁盘格式


伍、第五章-Linux的文件权限与目录配置


5.2 Linux文件权限概念

5.2.1 Linux文件属性-pg152

执行操作

ls -al

ll

可以显示文件的文件名和相关属性,如下:

dr-xr-x--- 5 root root 4096 May 29 16.08 .
//[1] [2] [3] [4] [5] [6] [7]
//[权限] [链接] [拥有者] [用户组] [文件容量] [修改日期] [文件名]

详细介绍第一栏[1]的十位字符所代表的含义

  • 第一栏代表这个文件的类型与权限(permission)

    • 第一个字符代表这个文件是目录、文件或链接文件等;
    • 当为[d]则是目录,如d---------;
    • 当为[-]则是文件,如-rwx------;
    • 当为[l]则是链接文件,如lrwx------;
    • 当为[b]则是设备文件里面的可供存储的周边设备(可按随机读写的设备),如brwx------;
    • 当为[c]则是设备文件里面的串行端口设备,如crwx------;
    • 接下来的字符中,以三个为一组,且均为【rwx】的三个参数的组合。其中,[r]代表可读(read)、[w]代表可写(write)、[x]代表可执行(execute)。要注意的是这三个权限的位置不会改变,如果没有权限,就会出现减号[-]而已。
    • 第一组为文件拥有者可具备的权限
    • 第二组为加入此用户组之账号的权限
    • 第三组为非本人且没有加入本用户组的其他账号的权限
  • 第二栏表示有多少文件名链接到此节点(inode)

    每个文件都会将它的权限与属性记录到文件系统的inode中,不过,我们使用的目录树却是使用文件名来记录,因此每个文件名就会链接到一个inode,这个属性记录的就是有多少不同的文件名链接到相同的一个inode号码。

  • 第三栏表示这个文件(或目录)的拥有者账号

  • 第四栏表示这个文件的所属用户组

  • 第五栏为这个文件的容量大小,默认单位为Bytes

  • 第六栏为这个文件的创建日期或是最近的修改日期

  • 第七栏为这个文件名

5.2.2 如何修改文件属性与权限-pg156

  • 修改所属用户组,chgrp

    这个命令是change group的缩写,用以修改一个文件的用户组,不过被修改的组名必须要在/etc/group文件中存在才行,否则会显示错误。

    //把a的拥有者修改b
    chgrp a b
    
  • 修改文件拥有者,chown

    这个命令是change owner的缩写,用以修改文件拥有者,用户必须是已经存在系统中的账号,也就是在/ect/passwd这个文件中有记录的用户名称才能修改。

    //把b的拥有者修改为a
    chown a b
    
  • 复制文件命令,cp

    cp操作会复制执行者的属性与权限,但是无法修改

    cp 源文件 目标文件
    //复制一个与文件a一样属性的文件b
    cp a b
    
  • 修改权限,chmod

    **chmod**用于修改文件权限,权限有两种:使用数字或是符号来进行权限的修改。

    • 数字类型修改文件权限

      Linux文件的基本权限就有9个,分别是拥有者(owner)、所属群组(group)、其他人(others)三种身份各有自己的读(read)、写(write)、执行(execute)权限三个一组,可以使用数字来代表各个权限,如下:

      r:4
      w:2
      x:1
      

      每种身份各自的三个权限数字是需要累加的,例如当权限是[-rwxrwx—],数字则是:

      owner = rwx = 4+2+1 = 7
      group = rwx = 4+2+1 = 7
      others = --- = 0+0+0 = 0
      

      当修改权限时,若要修改.txt这个文件所有的权限都设置启用([-rwxrwxrwx]),那么就执行:

      chmod 777 .txt
      
    • 符号类型修改文件权限

      chmodu(user)+(加入)r文件或目录
      g(group)-(移除)w
      o(others)=(设置)x
      a(all)

      按照上一个需求,符号修改的操作方式是:

      chmod a = rwx .txt
      

5.2.4 Linux文件种类与扩展名-pg163

cat:将一个文件内容读出来的命令

//可以看到文件内容
cat ~/.txt

5.3 Linux目录配置

5.3.1 Linux目录配置的依据————FHS-pg165

可分享(shareable)不可分享(unshareable)
不变(static)/usr(软件存放处)/etc(配置文件)
/opt(第三方辅助软件)/boot(启动与内核文件)
可变动(variable)/var/mail(用户邮箱)/var/run(程序相关)
/var/spool/news(新闻组)/var/lock(程序相关)

事实上,FHS针对目录树架构仅定义出三层目录下面应该放置什么数据而已,分别是下面这三个目录的定义:

  • /(root,根目录):与启动系统有关;

  • /usr(unix software resource):与软件安装/执行有关;

  • /var(variable):与系统运行过程有关。

根目录(/)的意义与内容

根目录是整个系统最重要的一个目录,因为不但所有的目录都是由根目录衍生出来,同时根目录也与启动、还原、系统修复等操作有关。

因此,根据FHS标准建议:根目录(/)所在分区应该越小越好,且应用程序所安装的软件最好不要与根目录放在同一个分区,保持根目录越小越好。如此不但性能较佳,根目录所在的文件系统也较不容易发生问题。

目录应放置文件内容
第一部分:FHS要求必须要存在的目录
/bin系统有很多存放执行文件的目录,但/bin比较特殊。因为/bin放置的是在单人维护模式下还能够被使用的命令。在/bin下面的命令可以被root与一般账号使用,主要有:cat、chmod、chown、date、mv、mkdir、cp、bash等常用的命令。
/boot这个目录主要是放置启动会使用到的文件,包括Linux内核文件以及启动选项与启动所需配置文件等。Linux内核常用的文件名为:vmlinuz,如果使用的是grub2这个启动引导程序,则还会存在/boot/grub2/这个目录。
/dev在Linux系统上,任何设备与接口设备都是以文件的形式存在于这个目录当中。你只要通过读写这个目录下面的某个文件,就等于读写某个设备,比较重要的文件有/dev/null/dev/zero、/dev/tty、/dev/loop*、/dev/sd*等。
/etc系统主要的配置文件几乎都放在这个目录内,例如人员的账号密码文件、各种服务的启动文件等。一般来说,这个目录下的各文件属性是可以让一般用户查看的,但是只有root有权利修改。FHS建议不要放置可执行文件(binary)在这个目录中。比较重要的文件有:/etc/modprobe.d/、/etc/passwd、/etc/fstab、/etc/issue等。另外FHS还规范几个重要的目录最好要存在/etc/目录下:
- /etc/cpt(必要):这个目录在放置第三方辅助软件/opt的相关配置文件;
- /etc/X11/(建议):与X Window有关的各种配置文件都在这里,尤其是xorg.conf这个X Server的配置文件;
- /etc/sgml/(建议):与SGML格式有关的各项配置文件;
- /etc/xml/(建议):与XML格式有关的各项配置文件;
/lib系统的函数库非常多,而/lib放置的则是在启动时会用到的函数库,以及在/bin或/sbin下面的命令会调用的函数库而已。什么是函数库?你可以将它想成是外挂,某些命令必须要有这些外挂才能够顺利完成程序的执行之意,另外FSH还要求下面的目录必须要存在:
- /lib/modules/:这个目录主要放置可抽换式的内核相关模块(驱动程序)。
/mediamedia是媒体的英文,顾名思义,这个/media下面放置的就是可删除的设备,包括软盘、光盘、DVD等设备都暂时挂载于此。常见的文件名有:/media/floppy、/media/cdrom等。
/mnt如果你想要暂时挂载某些额外的设备,一般建议你可以放置到这个目录中。在早些时候,这个目录的用途和/media相同。只是有了/media之后,这个目录就暂时用来挂载了。
/opt这个是给第三方辅助软件放置的目录。什么是第三方辅助软件?举例来说,KDE这个桌面管理系统是一个独立的软件,不过它可以安装到Linux系统中,因此KDE的软件就建议放置到此目录下。另外,如果你想要自行安装额外的软件(非原来的发行版提供),那么也能够将你的软件安装到这里来。不过,以前的Linux系统中,我们还是习惯放置在/usr/local目录下。
/run早期的FHS规定系统启动后所产生的各项信息应该要放置到/var/run目录下,新版的FHS则规范到/run下面,由于/run可以使用内存来模拟,因此性能上会好很多。
/sbinLinux系统有非常多命令是用来设置系统环境的,这些命令只有root才能够用来设置系统,其他用户最多只能用来查询而已。放在/sbin下面的为启动过程中所需要的,里面包括了启动、修复、还原系统所需要的命令。至于某些服务器软件程序,一般则是放置到/usr/sbin/当中。至于本机自行安装的软件所产生的系统执行文件(system binary),则放置到/usr/local/sbin/当中了。常见的命令包括:fdisk、fsck、ifconfig、mkfs等。
/srvsrv可以视为service的缩写,是一些网络服务启动之后,这些服务所需要使用的数据目录,常见的服务例如WWW、FTP等。举例来说。WWW服务器需要的网页数据就可以放置在/srv/www/里面。不过,系统的服务数据如果尚未要提供给因特网任何人浏览的话,默认还是建议放置到/var/lib下面即可。
/tmp这是让一般用户或是正在执行的程序暂时放置文件的地方。这个目录是任何人都能够存放的,所以你需要定期地清理一下。当然,重要数据不可放置在此目录。因为FHS甚至建议在启动时,应该要将/tmp下的数据都删除。
/usr第二层FHS设置,后续介绍。
/var第二层FHS设置,主要为放置变动性的设置,后续介绍。
第二部分:FHS建议可以存在的目录
/home这是系统默认的用户家目录(home directory)。在你新增应该一般用户账号时,默认的用户家目录都会规范到这里来,比较重要的是家目录有两种代号:
- ~:代表目前这个用户的家目录;
- ~dmtsai:则代表dmtsai的家目录。
/lib用来存放与/lib不同的格式的二进制函数库,例如支持64位的/lib64函数库等。
/root系统管理员(root)的家目录,之所以放在这里,是因为如果进入单人维护模式而仅挂载根目录时,该目录就能够拥有root的家目录,所以我们会希望root的家目录与根目录放置在同一个分区中。

Linux下几个也非常重要的目录

目录应放置文件内容
/lost+found这个目录是使用标准的ext2、ext3、ext4文件系统格式才会产生的一个目录,目的在于当文件系统发生错误时,将一些遗失的片段放置在这个目录下,不过如果使用的是xfs文件系统的话,就不会存在这个目录。
/proc这个目录本身是一个虚拟文件系统(virtual filesystem),它放置的数据都是在内存中,例如系统内核、进程信息(process)、外接设备的状态及网络状态等。因为这个目录下的数据都是在内存当中,所以本身不占任何硬盘空间。比较重要的文件例如:/proc/cpuinfo\/proc/dma\/proc/interrupts\/proc/ioports\/proc/net/*等。
/sys这个目录其实跟/proc非常相似,也是一个虚拟的文件系统,主要也是记录内核与系统硬件信息相关的内容。包括目前已加载的内核模块与内核检测到的硬件设备等,这个目录同样不占硬盘容量。

/usr的意义与内容

根据FHS的基本定义,/usr里面放置的数据属于可分享与不可变动(shareable,static)。

usr是UNIX Software Resource的缩写,这个目录有点内似于Windows系统的“C:\Windows\(当中的一部分)+C:\Program Files\”这两个目录的综合体。

目录应放置文件内容
第一部分:FHS要求必须要存在的目录
/usr/bin/所以一般用户能够使用的命令都放在这里。目前新的CentOS 7已经将全部的用户命令放置于此,而使用链接文件的方式将/bin链接至此。也就是说,/usr/bin与/bin是一模一样的。另外,FHS要求在此目录下不应该有子目录。
/usr/lib/基本上,与/lib功能相同,所以/lib就是链接到此目录中。
/usr/local/系统管理员在本机安装自己下载的软件(非发行版默认提供者)。建议安装到此目录,这样会比较便于管理。举例来说,你的发行版提供的软件较旧,你想安装较新的软件但又不想删除旧版,此时你可以将新版软件安装于/usr/local/目录下,可与原先的旧版软件有分别。你可以自行到/usr/local去看看,该目录下也是具有bin、etc、include、lib...的子目录。
/usr/sbin/非系统正常运行所需要的系统命令,最常见的就是某些网络服务器软件的服务命令(daemon)。不过基本功能与/sbin也差不多,因此目前/sbin就是链接到此目录中的。
/usr/share/主要放置只读的数据文件,当然也包括共享文件。、在这个目录下放置的数据几乎是不分硬件架构的可读取的数据,因为几乎都是文本文件。在此目录下常见的还有这些子目录:
- /usr/share/man:在线帮助文件;
- /usr/share/doc:软件的说明文档;
- /usr/share/zoneinfo:与时区有关的时区文件。
第二部分:FHS建议可以存在的目录
/usr/games/与游戏比较相关的数据放置处。
/usr/include/c/c++等程序语言的头文件(header)与包含文件(include)放置处,当我们以Tarball方式(*.tar.gz的方式安装软件)安装某些程序时,会使用到里面的许多文件。
/usr/libexec/某些不被一般用户常用的执行文件或脚本(script)等,都会放置在此目录中。例如大部分的X窗口下面的操作命令,很多都是方在此目录下。
/usr/lib/与/lib/功能相同,因此目前/lib就是链接到此目录中。
/usr/src/一般源代码建议放置到这里,src有source的意思。至于内核源代码则建议放置到/usr/src/Linux/目录下。

/var的意义与内容

目录应放置文件内容
第一部分:FHS要求必须要存在的目录
/var/cache/应用程序本身运行过程中会产生的一些缓存。
/var/lib/程序本身执行的过程中,需要使用到的数据文件放置的目录。在此目录下各自的软件应该要有各自的目录。举例来说,MySQL的数据库放置到/var/lib/mysql/而rpm的数据库则放到/var/lib/rpm中。
/var/lock/某些设备或是文件资源一次只能被一个应用程序所使用,如果同时有两个程序使用该设备时,就可能产生一些错误的状况,因此就得要将该设备上锁(lock),以确保该设备只会给单一软件所使用。举例来说,刻录机正在刻录一张光盘,你想一下会不会有两个人同时在使用一个刻录机刻盘?如果两个人台式刻录,那光盘写入的是谁的数据?所以当第一个人在刻录时刻录机就会被上锁,第二个人就得要该设备被解除锁定(就是前一个人用完了)才能够继续使用,目前此目录也已经挪到/run/lock中。
/var/log/重要到不行。这是日志文件放置的目录,里面比较重要的文件有/var/log/messages、/var/log/wtmp(记录登录信息)等。
/var/mail/放置个人电子邮箱的目录,不过这个目录也被放置到/var/spool/mail/目录中,通常这两个目录是互为链接文件。
/var/run/某些程序或是服务启动后,会把它们的PID放置在这个目录下,至于PID的意义我们会在后续章节提到,与/run相同,这个目录链接到/run目录。
/var/spool/这个目录通常放置一些队列数据,所谓的队列就是排队等待其他程序使用的数据,这些数据被使用后通常都会被删除。举例来说,系统收到新邮件会放置到/var/spool/mail/中,但用户收下该邮件后该封信原则上就会被删除,邮件如果暂时寄不出去会被放到/var/spool/mqueue/中,等到被送出后就被删除。如果是计划任务数据(crontab),就会被放置到/var/spool/cron/目录中。

5.3.2 目录树(directory tree)-pg169

在Linux下面,所有的文件与目录都是由根目录开始的。那是所有目录与文件的源头,然后在一个一个的分支下来,有点像是树枝状,因此,我们也称这种目录配置方式为:目录树(directory tree),这个目录有什么特殊?它主要的特征有:

  • 目录树的启动点为根目录(/,root);、

  • 每一个目录不止能使用本地分区的文件系统,也可以使用网络上的文件系统。举例来说,可以利用Network File System(NFS)服务器挂载某特定目录等;

  • 每一个文件在此目录树中的文件名(包含完整路径)都是独一无二的。

5.3.3 绝对路径与相对路径-pg170

根据文件名写法的不同,也可将所谓的路径(path)定义为绝对路径(absolute)与相对路径(relative)。这两种文件名/路径的写法依据是这样的:

  • 绝对路径:由根目录(/)开始写起的文件名或目录名称,例如/home/dmtsai/.bashrc;

  • 相对路径:相对于目录路径的文件名写法,例如./home/dmtsai或…/…/home/dmtsai等,反正开头不是/就属于相对路径的写法。

例子,你目前在/home这个目录下,如果想要进入/var/log这个目录时,可以怎么写?

1. cd /var/log(absolute)
2. cd ../var/log(relative)

因为你在/home下面,所以要回到上一层(…/)之后,才能继续往/var来移动。特别注意这两个特殊的目录:

  • .: 代表当前的目录,也可以使用./来表示;

  • …: 代表上一层目录,也可以使用…/来表示。

例题

如何先进入/var/spool/mail/目录,再进入到/var/spool/cron/目录中呢?

**答:**由于/var/spool/mail与/var/spool/cron是同样在/var/spool/目录中,因此最简单的命令执行方法为:

1. cd /var/spool/mail
2. cd ../cron

例题

网络文件常常提到类似“./run.sh”之类的数据,这个命令的意义是什么?

**答:由于命令的执行需要变量(bash章节才会提到)的支持,若你的执行支持放置在本目录,并且本目录并非常规的执行文件目录(/bin,/usr/bin等为常规),此时要执行命令就得要严格指定该执行文件。“/”代表“本目录”**的意思,所以“./run.sh”代表“执行本目录下名为run.sh的文件”。


陆、第六章-Linux文件与目录管理


6.1 目录与路径

6.1.1 绝对路径与相对路径-pg176

  • 绝对路径:路径的写法“一定由根目录(/)写起”,例如/usr/share/doc。

    • 绝对路径的正确度要比较好。

    • 如果在写程序(shell脚本)来管理系统的条件下,务必使用绝对路径。

  • 相对路径:路径的写法“不是由根目录(/)写起”,例如由/usr/share/doc要到/usr/share/man下面时,可以写成:“cd …/main”。

6.1.2 目录的相关操作-pg176

比较特殊的目录:

  1. . 代表此层目录
  2. … 代表上层目录
    • 代表前一个工作目录
  3. ~ 代表目前使用者身份所在的家目录
  4. -account 代表account这个使用者的家目录(account是个账户名称)

几个常见的处理目录的命令:

  • cd(change directory,切换目录)

利用相对路径的写法必须要确认你目前的路径才能正确地去到想要去的目录。

回到上层目录可以用 “cd …”,这个命令太常见,就不阐述了。

  • pwd(print working directory,显示目前所在的目录)

选项与参数:

-p : 显示出真正的路径,而非使用链接(link)路径。

  • mkdir(make directory,建立新目录)

在默认的情况下,你所需的目录得一层一层地建立才行。

选项与参数:

-m : 设置文件的权限,直接设置,不使用默认权限(umask)

可以利用-m来强制设置一个新目录相关的权限。比如“mkdir -m 711 test”就是给予test一个drwx–x–x的权限。

-p : 帮助你直接将所需要的目录(包括上层目录)递归创建

执行“mkdir -p /home/bird/test”,系统就会自动帮你依序生成目录。并且,如果该目录本来存在时,系统也不会显示错误信息。不过,不建议常用-p这个选项,因为担心如果打错字,那么目录名称就会变得乱七八糟。

  • rmdir(remove directory,删除空目录)

选项与参数:

-p : 连同上层“空的”目录也一起删除

目录需要一层一层删除才行,而且被删除的目录里面必定不能存在其他的目录或文件,这也是所谓的空目录(empty directory)的意思。

如果要将所有目录下的东西都删除?这个时候就必须使用【rm -f test】。不过,还是使用rmdir比较安全。

6.1.3 关于执行文件路径的变量:$PATH-pg179

“为什么我可以在任何地方执行/bin/ls这个命令?”

“这是因为环境变量PATH的帮助所致。”

echo $PATH
(显示)/usr/local/sbin:/usr/local/bin:/bin:/usr/sbin:/usr/bin:/root/bin

echo有“显示,打印”的意思,PATH前面加的 $ 表示后面接的是变量,所以会显示出目前的PATH。

PATH(一定是大写)这个变量的内容是由一堆目录所组成,每个目录中间用冒号(:)来隔开,每个目录有顺序之分。

例题:

假设你是root,如果你将ls由/bin/ls移动成为/root/ls(可用【mv /bin/ls /root】命令完成),然后你自己本身也在/root目录下,请问(1)你能不能直接输入ls来执行?(2)若不能,你该如何执行ls这个命令?(3)若要直接输入ls即可执行,又该如何进行?

答:

由于这个例题的重点是将某个执行文件移动到非正规目录去,所以我们先要进行下面的操作才行(务必先使用su - 切换成为root身份):

mv /bin/ls /root
(mv为移动,可将文件在不同的目录间进行移动操作)

(1)接下来不论你在哪个目录下面输入任何与ls相关的命令,都没有办法顺利地执行ls。也就是说,你不能直接输入ls来执行,因为/root这个目录并不在PATH指定的目录中,所以,即便你在/root目录下,也不能够查找到ls这个命令。

(2)因为这个ls确实存在与/root下面,并不是被删除了。所以我们可以通过使用绝对路径或是相对路径直接指定这个执行文件,下面的两个方法都能够执行ls这个命令:

/root/ls	(直接用绝对路径指定改文件名)
./ls	    (因为在/root目录下,就用./ls来指定)

(3)如果想要让root在任何目录均可执行/root下面的ls,那么就将/root加入PATH当中即可。加入的方法很简单,就像下面这样:

PATH = “${PATH}:/root”

上面这个做法就能够将/root加入到执行文件查找路径PATH中了。**另外,除了 P A T H 之 外 , 如 果 想 要 更 明 确 地 定 义 出 变 量 的 名 称 , 可 以 使 用 大 括 号 PATH之外,如果想要更明确地定义出变量的名称,可以使用大括号 PATH使{PATH}来处理变量的调用。**如果确定这个例题进行的没有问题,请将ls移回/bin下面,不然系统会挂。

mv /root/ls /bin

某些情况下,即便你已经将ls移回了/bin目录,不过系统还是会告诉你无法处理/root/ls。很可能是因为指向系统参数被缓存的关系。不要紧张,只要注销(exit)再登录(su -)就可以继续快乐地使用ls命令了。

总结:

  • 不同的身份用户默认的PATH不同,默认能够随便执行的命令也不同(如root与dmtsai)

  • PATH是可以修改的

  • 使用绝对路径或相对路径直接指定某个命令的文件名来执行,会比查找PATH来的正确

  • 命令应该要放置到正确的目录下,执行才会比较方便

  • 本目录(.)最好不要放到PATH当中


6.2 文件与目录管理

6.2.1 文件与目录查看:ls-pg181

ls [-aAdfFhilnrRST] 文件名或文件目录
ls [--color={never,auto,always}] 文件名或文件目录
ls [--full-time] 文件名或文件目录

选项与参数:

  • -a : 全部的文件,连同隐藏文件(开头为.的文件)一起列出来;

  • -A : 全部的文件,连同隐藏文件,但不包括.与…这两个目录;

  • -d : 仅列出目录本身,而不是列出目录内的文件数据;

  • -f : 直接列出结果,而不进行排序(ls默认会以文件名排序);

  • -F : 根据文件、目录等信息,给予附加数据结构,例如:

      • : 代表可执行文件;
    • / : 代表目录;
    • = : 代表socket文件;
    • | : 代表FIFO文件;
  • -h : 将文件容量以人类较易读的方式(例如GB、KB等)列出来;

  • -i : 列出inode号码,inode的意义下一章将会介绍;

  • -l : 详细信息显示,包含文件的属性与权限等数据;(很多版本简化为ll)

  • -n : 列出UID与GID而非使用者与用户组的名称(UID与GID会在账号管理提到);

  • -r : 将排序结果反向输出,例如:原本文件名由小到大,反向则为由大到小;

  • -R : 连同子目录内容一起列出来,等于该目录下的所有文件都会显示出来;

  • -S : 以文件容量大小排序,而不是用文件名排序;

  • -t : 依时间排序,而不是用文件名。

  • –color=never : 不要依据文件特性给予颜色显示;

  • –color=always : 显示颜色;

  • –color=auto : 让系统自行依据设置来判断是否给予颜色。

  • –full-time : 以完整时间模式(包括年、月、日、时、分)输出;

  • –time={atime,ctime} : 输出access时间或改变权限属性时间(ctime),而非内容修改时间(modification time)。

当只执行ls时,默认显示为:非隐藏文件的文件名、以文件名进行排序及文件名代表的颜色显示。

6.2.2 复制、删除与移动:cp、rm、mv-pg183

  • cp(copy,复制文件或目录)
cp [-adfilprsu] 源文件(source) 目标文件(destination)
cp [options] source1 source2 ... directory

选项与参数:

  • -a : 相当于-dr --preserve=all的意思,至于dr请参考下列说明;(将文件的所有特性都复制过来)

  • -d : 若源文件为链接文件的属性(link file),则复制链接文件属性而非文件本身;

  • -f : 为强调(force)的意思,若目标文件已经存在且无法开启,则删除后再尝试一次;

  • -i : 若目标文件(destination)已经存在时,在覆盖时会先询问操作的进行;

  • -l : 进行硬链接(hard link)的链接文件建立,而非复制文件本身;

  • -p : 连同文件的属性(权限、用户、时间)一起复制过去,而非使用默认属性;

  • -i : 递归复制,用于目录的复制操作;

  • -s : 复制成为符号链接文件(symbolic link),亦即“快捷方式”文件;

  • -u : destination比source旧才更新destination,或destination不存在的情况下才复制;

  • –preserve=all : 除了-p的权限相关参数外,还加入SELinux的属性,links、xattr等也复制。

注意:

如果源文件有两个以上,则最后一个目标文件一定要是“目录”才行。

想要复制到目前的目录,最后得加上“.”才行。

cp /var/log/wtmp .

复制(cp)这个命令是非常重要的,不同身份者执行这个命令会有不同的结果产生,尤其是那个-a、-p的选项,对于不同的身份来说,差异则非常大。

如果没有加上任何选项时,cp复制的是原始文件,而非链接文件的属性。若要复制链接文件的属性,就要使用-d。

  • rm(remove,删除文件或目录)
rm [-fir] 文件或目录

选项与参数:

  • -f : 就是force的意思,忽略不存在的文件,不会出现警告信息;

  • -i : 交互模式,在删除前会询问使用者是否操作;

  • -r : 递归删除,最常用于目录的删除,这是非常危险的选项

注意:

通过通配符(*)的帮忙,将/temp下面开头为bashrc的文件名通通删除:

rm -i bashrc*

注意那个星号*,代表0到无穷多个任意字符,很好用的东西。

一个问题:

\rm -r /temp/etc

在命令前加反斜线(\),可以忽略掉alias的指定选项。

  • mv(move,移动文件或目录,或重命名)
mv [-fiu] source destination
mv [options] source1 source2 .. directory

选项与参数:

  • -f : force强制的意思,如果目标文件已经存在,不会询问而直接覆盖;

  • -i : 若目标文件(destination)已经存在时,就会询问是否覆盖;

  • -u : 若目标文件已经存在时,且source比较新,才会更新(update)。

重命名某个文件:

mv mytest mytest2

6.2.3 获取路径的文件名与目录名称-pg186

basename /etc/sysconfig/network
(结果)network	//取得最后的文件名
dirname /etc/sysconfig/network
(结果)/etc/sysconfig	//取得的变成了目录名

6.3 文件内容查看

  • cat由第一行开始显示文件内容;

  • tac从最后一行开始显示,可以看出tac是cat的倒着写;

  • nl显示的时候,同时输出行号;

  • more一页一页地显示文件内容;

  • less与more类似,但是比more更好的是,它可以往前翻页;

  • head只看前面几行;

  • tall只看后面几行;

  • od以二进制的方式读取文件内容。

6.3.1 直接查看文件内容-pg187

直接查看一个文件的内容可以使用cat/tac/nl这几个命令。

  • cat(concatenate,串联),主要功能是将一个文件的内容连续打印在屏幕上面。
cat [-AbEnTv]

选项与参数:

- -A : 相当于-vET的整合选项,可列出一些特殊字符而不是空白而已(完整显示信息);

- -b : 列出行号,仅针对非空白行做行号显示,空白行不标行号;

- -E : 将结尾的换行符$显示出来;

- **<font color=red>-n : 打印出行号,连同空白行也会有行号,与-b的选项不同;</font>**

- -T : 将[tab]按键以^I显示出来;

- -v : 列出一些看不出来的特殊字符。
  • tac(反向列示)
tac /etc/issue 

tac刚好是cat反写过来,所以它的功能就跟cat相反,cat是由第一行到最后一行连续显示在屏幕上,而tac则是由最后一行到第一行反向在屏幕上显示出来。

  • nl(添加行号打印)
nl [-bnw] 文件

选项与参数:

- -b : 指定行号指定的方式,主要有两种:
	
	-b a : 表示不论是否为空行,也同样列出行号(类似cat -n);
	
	-b t : 如果有空行,空的那一行不要列出行号(默认值)。

- -n : 列出行号表示的方式,主要有三种:
	
	-n ln : 行号在屏幕的最左方显示;

	-n rn : 行号在自己栏位的最右方显示,且不加0;
	
	-n rz : 行号在自己栏位的最右方显示,且加0。

- -w : 行号栏位的占用的字符数。

nl可以将输出的文件内容自动地加上行号,其默认的结果与cat -n有点不太一样,nl可以将行号做比较多的显示设计,包括位数是否自动补充0等的功能。

例:

nl -b a -n rz -w 3 、/etc/issue
(结果)001	\S
(结果)002	Kernel \r on an \m
(结果)003	

行号变成仅有的3位数

6.3.2 可翻页查看-pg188

  • more(一页一页翻动)
more /etc/man_db.conf

重点在最后一行,最后一行会显示出目前显示的百分比,而且还可以在最后一行输入一些有用的命令。

- 空格键(space) : 代表向下翻一页;

- Enter : 代表向下翻一行;

- /字符串 : 代表在这个显示的内容当中,向下查找字符串这个关键词;

- :f : 立刻显示出文件名以及目前显示的行数;

- q : 代表立刻立刻more,不再显示该文件内容;

- b或[ctrl]-b : 代表往回翻页,不过这操作只对文件有用,对管道无效。
  • less(一页一页翻动)
less /etc/man_db.conf

less的用法比起more又更加有弹性,在more的时候,我们并没有办法向前面翻,只能往后翻。

- 空格键(space) : 向下翻动一页;

- [pagedown] : 向下翻动一页;

- [pageup] : 向上翻动一页;

- /字符串 : 向下查找字符串的功能;

- ?字符串 : 向上查找字符串的功能;

- n : 重复前一个查找(与/或?有关);

- N : 反向的重复前一个查找(与/或?有关);

- g : 前进到这个数据的第一行;

- G : 前进到这个数据的最后一行去(注意大小写);

- q : 代表立刻立刻more,不再显示该文件内容。

6.3.3 数据截取-pg190

  • head(头部,取出前面几行)
head [-n number] 文件

选项与参数:

-n : 后面接数字,代表显示几行的意思。

系统默认的情况中,显示前面十行,若要显示前20行,就得要这样。

head -n 20 /etc/man_db.conf

如果后面100行的数据都不打印,只打印/etc/man_db.conf的前面几行:

head -n -100 /etc/man_db.conf
//-n -100 表示列出前面所有行数,但不包括后面100行
  • tail(尾巴,取出后面几行)
tail [-n number] 文件

选项与参数:

-n : 后面接数字,代表显示几行的意思;

-f : 表示持续刷新显示后面所接文件中的内容,要等到按下[ctrl]-c才会结束。

系统默认的情况中,显示后面十行,若要显示最后20行,就得要这样。

tail -n 20 /etc/man_db.conf

如果不知道/etc/man_db.conf有几行,却只想列出100行以后的数据:

tail -n +100 /etc/man_db.conf
//-n +100 表示该文件以后100行都会被列出来

例:

假如想要显示/etc/man_db.conf的第11行到第20行?

答:

先取前二十行,再取后十行,所以就是:

head -n 20 /etc/man_db.conf | tail -n 10

6.3.4 非纯文本文件:od-pg191

可以将数据文件(data file)或是二进制文件(binary file)的内容数据读出来。

od [-t TYPE] 文件

选项与参数:

-t : 后面可以接各种【类型(TYPE)】的输出,例如:

a : 利用默认的字符来输出;
c : 使用ASCII字符来输出;
d[size] : 利用十进制(decimal)来输出数据,每个整数占用size Bytes;
f[size] : 利用浮点数值(floatingl)来输出数据,每个整数占用size Bytes;
o[size] : 利用八进制(octal)来输出数据,每个整数占用size Bytes;
x[size] : 利用十六进制(hexadecimal)来输出数据,每个整数占用size Bytes;

例:

//请将/etc/issue这个文件的内容以八进制列出储存值与ASCII的对照表
od -t oCc /etc/issue

----------借楼----------

详细参见https://blog.csdn/qq_31246691/article/details/77282461

其实 od -t oCc /etc/issue 等价于 od -t oC -t c /etc/issue

C代表的是char的size,S代表short,I代表int,L代表long int;

F代表float,D代表double,L此时代表long double。

当执行od -t oc /etc/issue 时:

会发现上下无法对应上,这是因为,od命令默认是按Int读取数字的,而Int是按4字节分割的,一行只有16字节,当然只能分为四段,从而无法与下面对齐(下面是char,按照1个字节截取)。所以便有了oC,来使得数字也是按照char来截取,便可以与下面对齐。如下为 od -t oCc /etc/issue 执行结果:

6.3.5 修改文件时间或创建新文件:touch-pg192

  • 修改时间(modification time,mtime):

    当该文件的【内容数据】变更时,就会更新这个时间,内容数据指的是文件的内容,而不是文件的属性或权限。

  • 状态时间(status time,ctime):

    当该文件的【状态(status)】改变时,就会更新这个时间,举例来说,像是权限与属性被更改了,都会更新这个时间。

  • 读取时间(access time,atime):

    当【该文件的内容被读取】时,就会更新这个读取时间(access),举例来说,我们使用 cat 去读取/etc/man_db.conf,就会更新该文件的atime。

touch [-acdmt]

选项与参数:

-a : 仅自定义access time;

-c : 仅修改文件的时间,若该文件不存在则不新建新文件;

-d : 后面可以接欲自定义的日期而不用目前的日期,也可以使用–date=“日期或时间”;

-m : 仅修改mtime;

-t : 后面可以接欲自定义的时间而不用目前的时间,格式为[YYYYMMDDhhmm]。

例:

//新建一个空文件
touch testtouch
//修改bashrc文件,将日期调整为两天前
touch -d “2 days ago” bashrc
//修改bashrc文件,将日期调整为2014/06/15 2:02
touch -t 201406150202 bashrc

通过touch这个命令,可以轻易地自定义文件的日期与时间,并且也可以建立一个空文件。不过,要注意的是,即使我们复制一个文件时,复制所有的属性,但也没有办法复制ctime这个属性。ctime可以记录这个文件最近的状态(status)被改变的时间。


6.4 文件与目录的默认权限与隐藏权限

6.4.1 文件默认权限:umask-pg195

umask就是指定目前用户在建立文件或目录时候的权限默认值。

umask
(结果)0022
umask -S
u=rwx,g=rx。o=rx

查看的方式有两种,一种是直接输入umask,就可以看到数字类型的权限设置值,一种则是加上-S(Symbolic)这个选项,就会以符号类型的方式来显示出权限了。

注意:umask的数字指的是**该默认值需要减掉的权限**,第一组数字是特殊权限用的。

举例来说:因为umask默认是022,所以user并没有被拿掉任何权限,不过group和others的权限被拿掉了2(也就是w的权限),那么当用户:

  • 建立文件时:(-rw-rw-rw-) - (-----w–w-) ==> -rw-r–r–

  • 建立目录时:(drwxrwxrwx) - (d----w–w-) ==> drwxr-xr-x

root的umask默认值是022,这是基于安全的考虑,至于一般身份用户,通常它们的umask为002,即保留同用户组的写入权力,如果想更改umask的默认值,可以这样修改:

umask 002

6.4.2 文件隐藏属性-pg196

强调一点,chattr命令只能在ext2、ext3、ext4的Linux传统文件系统上面完整生效。

  • chatter(配置文件隐藏属性)
chatter [+-=][ASacdistu]

选项与参数:

+ : 增加某一个特殊参数,其他原本存在的参数则不动;

- : 删除某一个特殊参数,其他原本存在的参数则不动;

= : 直接设置参数,且仅保留后面接的参数;

A : 当设置了A这个属性时,若你在存取此文件(或目录)时,它的存取时间atime将不会被修改,可避免I/O较慢的机器过度的读写磁盘。(目前建议使用文件系统挂载参数处理这个项目);

S : 一般文件是非同步写入磁盘的,如果加上S这个属性时,当你进行任何文件的修改,这个修改会【同步】写入磁盘中。

a : 当设置a之后,这个文件将只能增加数据,而不能删除也不能修改数据,只有root才能设置这个属性;

c : 这个属性设置之后,将会自动的将此文件【压缩】,在读取的时候将会自动解压缩,但是在存储的时候,将会先进行压缩后再存储;

d : 当dump程序被执行的时候,设置d属性将可使该文件(或目录)不会被dump备份;

i : 这个i就很厉害了,它可以让文件【不能被删除、改名、设置链接也无法写入或新增数据。】对于系统安全性有相当大的助益,只有root能设置此属性;

s : 当文件设置了s属性时,如该文件被删除,它将会被完全的从硬盘中删除,所以如果误删,完全没法恢复;

u : 与s相反的,当使用u来配置文件时,如果该文件被删除了,则数据内容其实还存在磁盘中,可以使用来恢复该文件。

注意1:属性设置常见的是a与i的设置值,而且很多设置值必须要是root才能设置;

注意2:xfs文件系统仅支持AadiS而已。

  • lsattr(显示文件隐藏属性)
lsattr [-adR] 文件或目录

选项与参数:

-a : 将隐藏文件的属性也显示出来;

-d : 如果接的是目录,仅列出目录本身的属性而非目录内的文件名;

-R : 连同子目录的数据也一并列出来。

6.4.3 文件特殊权限:SUID、SGID、SBIT-pg198

  • Set UID

当s这个标志出现在文件拥有者的x权限上时,此时就被称为Set UID,简称SUID的特殊权限。

- SUID权限仅对于二进制程序(binary program)有效;

- 执行者对于该程序需要具有x的可执行权限;

- 本权限仅在执行该程序的过程中有效(run-time);

- 执行者将具有该程序拥有者(owner)的权限。

SUID仅可用在二进制程序上,不能够用在shell脚本上面。

  • Set GID

当s标志在文件拥有者的x项为SUID,那s在用户组的x则称为Set GID(SGID)。与SUID不同的是,SGID可以针对文件或目录来设置。

如果对于文件来说,SGID有如下功能:

- SGID对二进制程序有用;

- 程序执行者对于该程序来说,需具备x的权限;

- 执行者在执行的过程中将会获得该程序用户组的支持。

如果对于目录来说,SGID有如下功能:

- 用户若对于此目录具有r与x的权限时,该用户能够进入此目录;

- 用户在此目录下的有效目录组(effective group)将会变成该目录的用户组;

- 用途:若用户在此目录下具有w的权限(可以新建文件),则用户所建立的新文件,该文件的用户组与此目录的用户组相同。
  • Sticky Bit

这个Sticky Bit(SBIT)目前只针对目录有效,SBIT对目录的作用是:

- 当用户对于此目录具有w、x权限,即具有写入的权限;

- 当用户在该目录下建立文件或目录时,仅有自己与root才有权力删除该文件。

换句话说,当甲这个用户对于A目录具有用户组或其他人的身份,并且拥有该目录w的权限,这表示甲用户对该目录内任何人建立的目录或文件均可进行删除、更名、移动等操作。不过,如果将A的目录加上了SBIT的权限选项时,则甲只能够针对自己建立的文件或目录进行删除、更名、移动等操作,而无法删除它人的文件。

  • SUID/SGID/SBIT权限设置

    • 4为SUID

    • 2为SGID

    • 1为SBIT

假设要将一个文件权限改成【-rwsr-xr-x】时,由于s在用户权限中,所以是SUID,因此,在原来的755之前还要加上4,也就是【chmod 4755 filename】来设置。

**注意:**若x位为空,此时S与T就代表空的x命令。

6.4.4 观察文件类型:file-pg200

简单地先判断文件的格式是什么

//file 文件
file ~/.bashrc

6.5 命令与文件的查找

6.5.1 脚本文件的查找-pg201

  • which(查找【执行文件】)

这个命令是根据【PATH】这个环境变量所规范的路径,去查找执行文件的文件名。

which [-a] command

选项与参数:

-a : 将所有由PATH目录中可以找到的命令均列出,而不止第一个被找到的命令名称。

6.5.2 文件的查找-pg201

一般我们都是先使用whereis或是locate来检查,如果真的找不到了,才以find来查找。因为whereis只找系统中某些特定目录下面的文件而已,locate则是利用数据库来查找文件名,当然两者就相当的快速,并没有实际查找硬盘内的文件系统状态,比较省时间。

  • whereis(由一些特定的目录中查找文件)
whereis [-bmsu] 文件或目录名

选项与参数:

-l : 可以列出whereis会去查询的几个主要目录;

-b : 只找binary(二进制)格式的文件;

-m : 只找在说明文件manual路径下的文件;

-s : 只找source源文件;

-u : 查找不在上述三个项目当中的其他特殊文件。
  • locate/updatedb

    • updatedb:根据/etc/updatedb.conf的设置去查找系统硬盘内的文件,并更新/var/lib/mlocate;

    • locate:根据/var/lib/mlocate内的数据记录,找出用户所输入关键词的文件名。

locate [-ir] keyword

选项与参数:

-i : 忽略大小写的差异;

-c : 不输出文件名,仅计算找到的文件数量;

-l : 仅输出几行的意思;

-S : 输出locate所使用的数据库文件的相关信息,包括该数据库记录的文件/目录数量等;

-r : 后面可接正则表达式的显示方式。
  • find
find [PATH] [option] [action]

选项与参数:

1.与时间有关的选项:共有-atime、-ctime与-mtime,以-mtime说明。

-mtime n : n为数字,意义为在n天之前的【一天之内】被修改过内容的文件;

-mtime +n : 列出在n天之前(不含n天本身)被修改过内容的文件;

-mtime -n : 列出在n天之内(含n天本身)被修改过内容的文件;

-newer file: file为一个存在的文件,列出比file还要新的文件。

例子:

//将过去系统上面24小时内有修改过内容(mtime)的文件列出。
find / -mtime 0
//0代表目前的时间,所以,从现在开始到24小时前。
//寻找/etc下面的文件,如果文件日期比/etc/passwd新就列出。
find /etc -newer /etc/passwd 

2.与使用者或用户组名称有关的参数:

-uid n : n为数字,这个数字是使用者的账号ID,亦即UID,这个UID是记录在/etc/passwd里面;

-gid n : n为数字,这个数字是用户组名称的ID,亦即GID,这个GID是记录在/etc/group;

-user name : name为使用者账号名称,例如dmtsai;

-group name : name为用户组名称,例如users;

-nouser : 查找文件的拥有者不在/etc/passwd中;

-nogroup : 查找文件的拥护用户组不存在于/etc/group的文件。当你自行安装软件时,很可能该软件的属性当中并没有文件拥有者,这是可能的,这个时候,就可以使用-nouser或-nogroup查找。

3.与文件权限及名称有关的参数:

-name filename : 查找文件名称为filename的文件;

-size [+-]SIZE : 查找比SIZE还要大(+)或小(-)的文件,这个SIZE的规格有:

	c : 代表Bytes, k : 代表1024Bytes。所以,要找比50kB还要大的文件,就是【-size+50k】

-type TYPE : 查找文件的类型为TYPE的,类型主要有:一般正规文件(f),设备文件(b,c),目录(d),链接文件(l),socket(s),及FIFO(p)等属性。

-perm mode : 查找文件权限【刚好等于】mode的文件,这个mode为类似chmod的属性值;

-perm -mode : 查找文件权限【必须要全部囊括mode的权限】的文件;

-perm/mode : 查找文件权限【包含任一mode的权限】的文件,这个mode为类似chmod的属性值。

4.额外可进行的操作:

-exec command : command为其他命令,-exec后面可再接额外的命令来处理查找到的结果。

-print : 将结果打印到屏幕上,这个操作是默认操作。

例子:

find /usr/bin /usr/sbin -perm /7000 -exec ls -l () \; 
//注意到,那个-exec后面的ls -l就是额外的命令,命令不支持命令别名(-ll)

其中:

- {}代表的是由find找到的内容,结果会存放在{}中;

- -exec一直到\;是关键词,代表find额外操作的开始(-exec)到结束(\;),在这中间的就是find命令内的额外操作。在本例中就是【ls -l{}】;

- 因为【;】在bash环境下是有特殊意义的,因此利用反斜杠来转义。

#柒、第七章-Linux磁盘与文件系统管理


7.1 认识Linux文件系统

7.1.1 磁盘组成与分区的复习-pg210

磁盘分区表主要有两种格式,一种是限制较多的MBR分区表,一种是较新且限制较少的GPT分区表:

  • MBR分区表中,第一个扇区最重要,里面有:主引导记录(Master boot record,MBR)及分区表(partition table),其中MBR占用446B,而分区表则占用64B;

  • GPT分区表除了分区数量扩充较多之外,支持磁盘容量也可以超过2TB。

磁盘文件名:

  • /dev/sd[a-p][1-128] : 为物理磁盘的文件名;

  • /dev/vd[a-d][1-128] : 为虚拟磁盘的文件名。

7.1.2 文件系统特性-pg211

Linux的正统文件系统是ext2(Linux second Extended file system,ext2fs)。

通常我们称呼一个可被挂载的数据为一个文件系统而不是一个分区。

文件系统通常会将这两部分的数据分别存放在不同的区块,权限与属性放置到inode中,至于实际数据则放置到数据区块中。另外,还有一个超级区块(superblock)会记录整个文件系统的整体信息,包括inode与数据区块的总量、使用量、剩余量等。

  • 超级区块:记录此文件系统的整体信息,包括inode与数据区块的总量、使用量、剩余量,以及文件系统的格式与相关信息等;

  • inode:记录文件的属性,一个文件占用一个inode,同时记录此文件的数据所在的区块号码;

  • 数据区块:实际记录文件的内容,若文件太大时,会占用多个区块。

7.1.3 Linux的ext2文件系统(inode)-pg212

文件系统一开始就将inode与数据区块规划好了,除非重新格式化(或利用resize2fs等命令修改其大小),否则inode与数据区块固定后就不再变动。

文件系统最前面有一个启动扇区(boot sector),这个启动扇区可以安装启动引导程序。

每一个区块群组(block group)的六个主要内容如下:

  • 数据区块(data block)

数据区块是用来放置文件数据的地方,在ext2文件系统中所支持的区块大小有1K,2K及4K三种。在格式化时区块的大小就固定了,且每个区块都有编号,以方便inode的记录。

Block大小1KB2KB4KB
最大单一文件限制16GB256GB2TB
最大文件系统总容量2TB8TB16TB

ext2文件系统的区块基本限值如下:

- 原则上,区块的大小与数量在格式化完就不能够再修改(除非重新格式化);

- 每个区块内最多只能够放置一个文件的数据;

- 承上,如果文件大于区块的大小,则一个文件会占用多个区块数量;

- 承上,若文件小于区块,则该区块的剩余容量就不能够再被使用了(磁盘空间会浪费)。
  • inode table(inode表)

inode记录的数据至少有下面这些:

- 该文件的读写属性(read、write、excute);
- 该文件的拥有者与用户组(owner、group);
- 该文件的大小;
- 该文件建立或状态改变的时间(ctime);
- 最近一次的读取时间(atime);
- 最近修改时间(mtime);
- 定义文件特性的标识(flag),如SetUID;
- 该文件真正内容的指向(pointer)。

inode的特色:

- 每个inode大小均固定为128B(新的ext4与xfs可设置256B);
- 每个文件都仅会占用一个inode而已;
- 承上,因此文件系统能够建立的文件数量与inode的数量有关;
- 系统读取文件时需要先找到inode,并分析inode所记录的权限与用户是否符合,若符合才能够读取区块的内容。

inode记录区块号码的区域定义为12个直接、一个间接、一个双间接与一个三间接记录区。

inode本身(128B),里面有12个直接指向区块号码的对照,这12条记录就能够直接取得区块号码。间接就是再拿一个区块来当做记录区块号码的记录区,如果文件太大,就会使用间接的区块来记录编号。

- 12个直接指向:12×1K=12K;
	由于是直接指向,所以总共可记录12条记录
- 间接:256×1K=256K;
	每条区块号码的记录会使用4B,因此1K的大小那个记录256条记录
- 双间接:256×256×1K=256^2^K
	第一层区块会指定256个第二层,每个第二层可以指定256个号码
- 三间接:256×256×256×1K=256^3^K
	第一层区块会指定256个第二层,每个第二层可以指定256个第三层,每个第二层可以指定256个号码
- 总额:将直接、间接、双间接、三间接相加,得到12+256+256×256+256×256×256(K)=16G
  • Superblock(超级区块)

超级区块是记录整个文件系统相关信息的地方,没有超级区块,就没有这个文件系统,它记录的信息主要有:

- 数据区块与inode的总量;
- 未使用与已使用的inode与数据区块、数量;
- 数据区块与inode的大小(block为1、2、3K,inode为128B或256B);
- 文件系统的挂载时间、最近一次写入数据的时间、最近一次检验磁盘(fsck)的时间等文件系统的相关信息;
- 一个有效位数值,若此文件系统已被挂载,则有效位为0,若未被挂载,则有效位为1.
  • Filesystem Description(文件系统描述说明)

这个区段可以描述为每个区块群组的开始于结束的区块,以及说明每个区块(超级区块、对照表、inode对照表、数据区块)分别介于哪一区块之间,这部分也能够用dumpe2fs来观察。

  • 区块对照表(block bitmap)

从区块对照表当中可以知道哪些区块是空的,因此我们的系统就能够很快速地找到可使用的空间来处理文件。

  • inode对照表(inode bitmap)

这个其实与区块对照表的功能类似,只是区块对照表记录的是使用与未使用的区块号码,inode对照表则是记录使用与未使用的inode号码。

  • dumpe2fs:查询ext系统超级区块信息的命令
dumpe2fs [-bh] 设备文件名

选项与参数:

-b : 列出保留为坏道的部分;

-h : 仅列出superblock的数据,不会列出其他的区段内容

7.1.4 与目录树的关系-pg217

  • 目录

当我们在Linux下的文件系统建立一个目录时,文件系统会分配一个inode与至少一块区块给该目录。其中,inode记录该目录的相关权限与属性,并可记录分配到的那块区块号码,而区块则是记录在这个目录下的文件名与该文件名占用的inode号码数据。

  • 文件

当我们在Linux下的ext2建立一个一般文件时,ext2会分配一个inode与相对于该文件大小的区块数量给该文件。

  • 目录树读取

当我们要读取某个文件时,就务必会经过目录的inode与区块,然后才能够找到那个待读取文件的inode号码,最终才会读取到该文件的区块中的数据。

由于目录树是由根目录开始读起,因此系统通过挂载的信息可以找到挂载点的inode号码,此时就能够得到根目录的inode内容,并依据该inode读取根目录的区块内的文件名数据,再一层一层的往下读到正确的文件名。

  • 文件系统大小与磁盘读取性能

磁盘分区的规划并不是越大越好,而是要针对主机的用途来进行规划才行。

7.1.5 ext2/ext3/ext4文件的存取与日志式文件系统的功能-pg219

假设我们想要新增一个文件,此时文件系统的操作是:

  1. 先确定用户对于欲新增文件的目录是否具有w与x的权限,若有的话才能新增;
  2. 根据inode对照表找到没有使用的inode号码,并将新文件的权限/属性写入;
  3. 根据区块对照表找到没有使用中的区块号码,并将实际的数据写入区块中,且更新inode的区块指向数据;
  4. 将刚刚写入的inode与区块数据同步更新inode对照表与区块对照表,并更新超级区块的内容。

一般来说,我们将inode对照表与数据区块称为数据存放区域,至于其他例如超级区块、区块对照表与inode对照表等区段就被称为元数据(metadata),因为超级区块、inode对照表及区块对照表的数据是经常变动的,每次新增、删除、编辑时都可能会影响到这三个部分的数据,因此才被称为**元数据**。

  • 数据的不一致(Inconsistent)状态

文件在写入文件系统时,因为某些原因导致系统中断,所以写入的数据仅有inode对照表及数据区块而已,最后一个同步更新元数据的步骤并没有完成,此时就会发生元数据的内容与实际数据存放区产生不一致(Inconsistent)的情况。

  • 日志式文件系统(Journaling filesystem)

简化一致性检查的步骤如下:

1. 预备:当系统要写入一个文件时,会先在日志记录区块中记录某个文件准备要写入的信息;
2. 实际写入:开始写入文件的权限与数据;开始更新metadata的数据;
3. 结束:完成数据与metadata的更新后,在日志记录区块当中完成该文件的记录。

7.1.6 Linux文件系统的运行-pg220

当系统加载一个文件到内存后,如果该文件没有被修改过,则在内存区段的文件数据会被设置为【干净(clean)】。但如果内存中的文件数据被更改过了,此时该内存中的数据会被设置为【脏的(Dirty)】,此时所有的操作都还在内存中执行,并没有写入到磁盘中。

Linux系统上面的文件系统与内存有非常大的关系:

- 系统会将常用的文件数据放置到内存的缓存区,以加速文件系统的读写操作;
- 承上,因此Linux的物理内存最后都会被用光,这是正常的情况,可加速系统性能;
- 你可以手动使用sync来强制内存中设置为Dirty的文件回写到磁盘中;
- 若正常关机时,关机命令会主动调用sync来将内存的数据回写入磁盘内;
- 但若不正常关机,由于数据尚未回写到磁盘内,因此重新启动后可能会花很多时候在进行磁盘校验,甚至可能导致文件系统的损坏(非磁盘损坏)。

7.1.7 挂载点的意义(mount point)-pg221

每个文件系统都有独立的inode、区块、超级区块等信息,这个文件系统要能够链接到目录树才能被我们使用。将文件系统与目录树结合的操作我们称为【挂载】。挂载点一定是目录,该目录为进入该文件系统的入口

同一个文件系统的某个inode只会对应到一个文件内容而已(因为一个文件占用一个inode),因此我们可以通过判断inode号码来确认不同文件名是否为相同的文件。

7.1.8 其他Linux支持的文件系统与VFS-pg221

所以Linux系统都是通过一个名为Virtual Filesystem Switch的内核功能去读取文件系统。也就是说,整个Linux识别的文件系统其实都是VFS在进行管理,我们用户并不需要知道每个硬盘分区上面的文件系统是什么,VFS会主动帮我们做好读取的操作。

7.1.9 XFS文件系统简介-pg222

  • ext系统当前比较伤脑筋的地方就是:支持度最广,但格式化超慢

  • XFS文件系统的配置

xfs文件系统在数据的分布上,主要规划为三个部分,一个数据区(data section)、一个文件系统活动登录区(log section)以及一个实时运行区(realtime section),这三个区域的数据内容如下:

- 数据区(data section)

基本上,数据区就跟我们之前谈到的ext系列一样,包括inode、数据区块、超级区块等数据都放置在这个区块。这个数据区与ext系列的区块群组类似,也是分为多个存储区群组(allocation groups)来分别放置文件系统所需要的数据(存储区群组和ext系列的区块群组类似(block groups))。
每个存储区群组都包含了:
	(1)整个文件系统的超级区块;
	(2)剩余空间的管理机制;
	(3)inode的分配与追踪。
此外,inode与区块都是系统需要用到时才动态配置产生,所以格式化操作超级快。

另外,与ext系列不同的是,xfs的区块与inode有多种不同的容量可供设置,区块容量可在512B~64KB调整,不过,Linux的环境下,由于存储控制的关系(页面文件pagesize的容量之故),因此最高可以使用的区块大小为4K而已。

- 文件系统活动登录区(log section)

在登录区这个区域主要被用来记录文件系统的变化,其实有点像是日志区。文件的变化会在这里记录下来,直到该变化完整地写入到数据区后,该条记录才会被结束。

- 实时运行区(realtime section)

当有文件要被建立时,xfs会在这个区段里面找一个到数个的extent区块,将文件放置在这个区块内,等到分配完毕后,再写入到data section的inode与区块中。这个extent区块的大小要在格式化的时候就先指定,最小值是4K最大可到1G。一般非磁盘阵列的磁盘默认为64K容量,而具有类似磁盘阵列的stripe情况下,则建议将extent设置为与stripe一样大,这个extent最好不要乱动,因为可能会影响到物理磁盘的性能。
  • XFS文件系统的描述数据观察
xfs info 挂载点|设备文件名

7.2 文件系统的简单操作

7.2.1 磁盘与目录的容量-pg224

  • df(列出文件系统的整体使用量)
df [-ahikHTm] [文件或目录名]

选项与参数:

-a : 列出所有的文件系统,包括系统的特有的/proc等文件系统;

-k : 以KBytes的容量显示各文件系统;

-m : 以MBytes的容量显示各文件系统;

**<font color=red>-h : 以人们较易阅读的GBytes、MBytes、KBytes等格式自行显示;</font>** 

-H : 以M=1000K替换M=1024K的进位方式;

-T : 连同该硬盘分区的文件系统名称(例如xfs)也列出;

**<font color=red>-i : 不用磁盘容量,而以inode的数量来显示。</font>**

由于df主要读取的数据几乎都是针对一整个文件系统,因此读取的范围主要是在超级区块内的信息,所以这个命令显示结果的速度非常快。在显示的结果中你需要特别留意的是根目录(/)的剩余容量。因为我们所有的数据都是由根目录衍生出来的。

  • du(查看文件系统的磁盘使用量(常用在查看目录所占的磁盘空间))
du [-ahskm] [文件或目录名]

选项与参数:

-a : 列出所有的文件与目录容量,因为默认仅统计目录下面的文件量;

-h : 以人们较易读的容量格式(G/M)显示;

**<font color=red>-s : 仅列出总量,而不列出每个各别的目录占用容量;</font>**

-S : 不包括子目录下的总计,与-s有点差别;

-k : 以KBytes的容量显示各文件系统;

-m : 以MBytes的容量显示各文件系统。

与df不一样的是,du这个命令其实会直接到文件系统内去查找所有的文件数据。

7.2.2 硬链接与符号链接-pg227

在Linux下面的链接文件有两种,一种是类似Windows的快捷方式功能的文件,可以让你快速地链接到目标文件(或目录);另一种则是通过文件系统的inode链接来产生新文件名,而不是产生新文件,这种称为**硬链接**(hard link)。

  • 硬链接(Hard Link,硬式链接或实际链接)

硬链接只是在某个目录下新增一条文件名链接到某inode号码的关联记录而已。

如果你将任何一个文件名删除,其实inode与区块都还是存在。

但是硬链接是有限制的:

- 不能跨文件系统
- 不能链接目录

如果使用硬链接到目录时,链接的数据需要连同被链接目录下面的所有数据都建立链接。

  • 符号链接(Symbolic Link,亦即快捷方式)

符号链接就是建立一个独立的文件,而这个文件会让数据的读取指向它链接的那个文件的文件名。

当源文件被删除之后,符号链接的文件会【打不开了】,会一直说【无法打开某文件】,实际上就是找不到原始文件名而已。

链接文件的重要内容就是它会写入目标文件的文件名。如果目标文件被删除了,那么整个环节就会无法继续进行下去,所以就会发生无法通过链接文件读取的问题。

整个符号链接与Windows的快捷方式可以给它划上等号,有符号链接所建立的文件为一个独立的新的文件,所以会占用inode与区块。

要制作链接文件就必须要使用ln这个命令:

ln [-sf] 源文件 目标文件

选项与参数:

-s : 如果不加任何参数就进行链接,那就是硬链接,至于-s就是符号链接;

-f : 如果目标文件存在时吗,就主动的将目标文件直接删除后再建立。
  • 关于目录的链接数量

当我们建立一个新的目录时,【新的目录的链接数为2,而上层目录的链接数则会增加1】。


7.3 磁盘的分区、格式化、检验与挂载

如果我们想要在系统里面新增一块磁盘时,应该有哪些操作需要做:

  1. 对磁盘进行区分,以建立可用的磁盘分区;
  2. 对该磁盘分区进行格式化(format),以建立系统可用的文件系统;
  3. 若想要仔细一点。则可对刚刚建立好的文件系统进行检验;
  4. 在Linux系统上,需要建立挂载点(亦即是目录),并将它挂载上来。

7.3.1 观察磁盘分区状态-pg232

  • lsblk列出系统上的所有磁盘列表

lsblk可以看成【list block device】的缩写,就是列出所有存储设备的意思。

lsblk [-dfimpt] [device]

选项与参数:

-d : 仅列出磁盘本身,并不会列出该磁盘的分区数据;

-f : 同时列出该磁盘内的文件系统名称;

-i : 使用ASCII的字符输出,不要使用复杂的编码(在某些环境下很有用);

-m : 同时输出该设备在/dev下面的权限信息(rwx的数据);

-p : 列出该设备的完整文件名,而不是仅列出最后的名字而已;

-t : 列出该磁盘设备的详细数据,包括磁盘阵列机制、预读写的数据量大小等。
  • blkid列出设备的UUID等参数

UUID是全局唯一标识符(universally unique identifier),Linux会将系统内所有的设备都给予一个独一无二的标识符,这个标识符就可以拿来作为挂载或使用这个设备或文件系统。

  • parted列出磁盘的分区表类型与分区信息
parted device name print

7.3.2 磁盘分区:gdisk/fdisk-pg233

MBR分区表请使用fdisk分区,GRP分区表请使用gdisk分区。

  • gdisk
gdisk 设备名称

不管进行什么操作,只要离开gdisk时按下【q】,那么所有的操作都不会生效,相反,按下【w】就是写入、操作生效的意思。

使用【p】可以列出目前这块磁盘的分区表信息。

使用【d】可以删除一个分区。

这个gdisk只有root才能执行,使用的设备文件名请不要加上数字,因为磁盘分区是针对整个磁盘设备而不是某个分区。

  • partprobe更新Linux内核的分区表信息
partprobe -s
  • fdisk
fdisk 设备名称

7.3.3 磁盘格式化(创建文件系统)-pg238

  • XFS文件系统mkfs.xfs

我们常听到的格式化其实应该称为创建文件系统(make filesystem)才合适,所以使用的命令是mkfs。

mkfs.xfs [-b bsize] [-d parms] [-i parms] [-l parms] [-f] [-r parms] 设备名称

选项与参数:

关于单元:下面只要谈到【数值】时,没有加单位则为Bytes值,可以用k、m、g、t、p(小写)等来解释比较特殊的是s这个单位它指的是扇区的【个数】。

-b : 后面接的是区块容量,可由512到64k,不过最大容量限制为Linux的4k;

-d : 后面接的是重要的data section的相关参数值,主要的值有:
	agcount=数值 : 设置重要几个存储群组的意思(AG),通常与CPU有关。
	agsize=数值 : 每个AG设置为多少容量的意思,通常agcount/agsize只选一个设置即可。
	file : 指的是【格式化的设备是个文件而不是个设备】的意思。(例如虚拟磁盘)
	size=数值 : data section的容量,亦即你可以不将全部的设备容量用完的意思。
	su=数值 : 当有RAID时,那个stripe数值的意思,与下面的sw搭配使用。
	sw=数值 : 当有RAID时,用于保存数据的磁盘数量(需扣除备份盘与备用盘)。
	sunit=数值 : 与su相当,不过单位使用的是【几个sector(512Bytes大小)】的意思。
	swidth=数值 : 就是su*sw的数值,但是以【几个sector(512Bytes大小)】来设置。

-f : 如果设备内已经有文件系统,则需要使用这个-f来强制格式化才行;

-i : 与inode有较相关的设置,主要的配置值有:
	size=数值 : 最小是356Bytes最大是2k,一般保留256就足够使用了。
	internal=[0|1] : log设备是否为内置?默认为1内置,如果要用外部设备,使用下面设置。
	logdev=device : log设备为后面接的那个设备上面的意思,需设置internal=0才可。
	size=数值 : 指定这块登录区的容量,通常最小得要有512个区块,大约2M以上才行。

-L : 后面接的这个文件系统的标头名称Label name的意思;

-r : 指定realtime section的相关设置值,常见的有:
	extsize=数值 : 就是那个重要的extent数值,一般不需设置,但有RAID时,最好设置与swidth的数值相同较佳,最小为4K最大为1G。
  • XFS文件系统for RAID性能优化(Optional)

磁盘阵列(RAID)就是通过将文件先细分为数个小型的分区区块(stripe)之后,然后将众多的stripes分别放到磁盘阵列里面的所有磁盘,所以一个文件是被同时写入到多个磁盘中,当然性能会更好一些。

为了文件的安全性,所以在这些磁盘里面,会保留数个(与磁盘阵列的规划有关)校验磁盘(parity disk),以及可能会保留一个以上的备用磁盘(spare disk),这些区块基本上会占用掉磁盘阵列的总容量,不过对于数据的安全会比较有保障。

那个分区区块stripe的数值大多介于4K和1M之间,这与你的磁盘阵列卡支持的选项有关。

stripe与你的文件数据容量以及性能相关性较高,
(1)当你的系统大多是大型文件时,一般建议stripe可以设置大一些,这样磁盘阵列读写的频率会降低,性能会提升。
(2)如果是用于系统,那么小文件比较多的情况下,stripe建议大约在64K左右可能会有较佳的性能。

  • ext4文件系统mkfs.ext4

如果想要格式化为ext4的传统Linux文件系统的话,可以使用mkfs.ext4这个命令。

mkfs.ext4 [-b bsize] [-L label] 设备名称

选项与参数:

-b : 设置区块的大小,有1K、2K、4K的容量;

-L : 后面接这个设备的标头名称。
  • 其他文件系统mkfs

mkfs其实是个综合命令而已,当我们使用mkfs -t xfs时,它就会跑去找mkfs.xfs相关的参数给我们使用。如果想知道系统还支持哪种文件系统的格式化功能,直接按[tab]就很清楚了。

//(找所有mkfs)
mkfs [tab] [tab]

7.3.4 文件系统检验-pg241

  • xfs_repair处理XFS文件系统
xfs_repair [-fnd] 设备名称

选项与参数:

-f : 后面的设备其实是个文件而不是实体设备;

-n : 单纯检查并不修改文件系统的任何数据(检查而已);

-d : 通常用在单人维护模式下面,针对根目录(/)进行检查与修复的操作,很危险,不要随便使用。

xfs_repair可以检查/修复文件系统,不过,因为修复文件系统是个很庞大的任务。修复时该文件系统不能被挂载。

  • fsck.ext4处理ext4文件系统

fsck是个综合命令,如果是针对ext4的话,建议直接使用fask.ext4来检测比较妥当。

fsck.ext4 [-pf] [-b 超级区块] 设备名称

选项与参数:

-p : 当文件系统在修复时,若有需要回复y的操作时,自动回复y来继续进行修复操作;

-f : 强制检查,一般来说,如果fsck没有发现任何unclean的标识,不会主动进入详细检查的,如果想要强制fsck详细检查,就得加上-f标识;

-D : 针对文件系统下的目录进行最佳化配置;

-b : 后面接超级区块的位置,一般来说这个选项用不到,但是如果你的超级区块因故损坏时,通过这个参数即可利用文件系统内备份的超级区块来尝试恢复,一般来说,超级区块备份在:1K区块放在8193,2K区块放在16384,4K区块放在32768。

注意:

通常只有身为root且你的文件系统有问题的时候才使用这个命令,否则在正常状况下使用此命令,可能会造成对系统的危害。

执行xfs_repair与fsck_ext4时,被检查的磁盘分区务必不可挂载到系统上,亦即是需要在卸载的状态。

7.3.5 文件系统挂载与卸载-pg243

挂载前,先确认几件事:

  • 单一文件系统不应该被重复挂载在不同的挂载点(目录)中;
  • 单一目录不应该重复挂载多个文件系统;
  • 要作为挂载点的目录,理论上应该都是空目录才行。(/mnt)

如果用来挂载的目录里面并不是空的,那么挂载了文件系统之后,原目录下的东西就会暂时地消失。

mount -a
mount [-l]
mount [-t 文件系统] LABEL='' 挂载点
mount [-t 文件系统] UUID='' 挂载点(推荐)
mount [-t 文件系统] 设备文件名 挂载点

选项与参数:

  • -a : 依照配置文件/etc/fstab的数据将所有未挂载的磁盘都挂载上来;

  • -l : 单纯的输入mount会显示目前挂载的信息,加上-l可增列Label名称;

  • -t : 可以加上文件系统种类来指定欲挂载的类型,常见的Linux支持类型有:xfs、ext3、ext4、reiserfs、vfat、iso9660(光盘格式)、nfs、cifs、smbfs(后三种为网络文件系统类型);

  • -n : 在默认的情况下,系统会将实际挂载的情况即时写入/etc/mtab中,以利其他程序的运行,但在某些情况下(例如单人维护模式)为了避免问题会刻意不写入,此时就得要使用 -n 选项;

  • -o : 后面可以接一些挂载时额外加上的参数。比方说账号、密码、读写权限等;

    • async,sync : 此文件系统是否使用同步写入(sync)或非同步(async)的内存机制,请参考文件系统运行方式,默认为async;
    • atime,noatime : 是否修改文件的读取时间(atime)。为了性能,某些时刻可使用noatime;
    • ro,rw : 挂载文件系统成为只读(ro)或可读写(rw);
    • auto,noauto : 允许此文件系统被以mount -a 自动挂载(auto);
    • dev,nodev : 是否允许此文件系统可建立设备文件?dev为可允许;
    • suid,nosuid : 是否允许此文件系统含有suid/sgid的文件格式;
    • exec,noexec : 是否允许此文件系统上拥有可执行二进制文件;
    • user,nouser : 是否允许此文件系统让任何使用者执行mount?一般来说,mount仅有root可以进行,但执行user参数,可以让一般user也能够对此分区进行mount;
    • default : 默认值为:rw、suid、dev、exec、nouser、and async;
    • remount : 重新挂载,这在系统出错,或重新更新参数时很有用。

系统指定类型的文件系统才需要进行挂载测试:

  • /etc/filesystems : 系统指定的测试挂载文件系统类型的优先级;
  • /proc/filesystems : Linux系统已知加载的文件系统类型。

Linux支持的文件系统的驱动程序都写在如下的目录中:

  • /lib/modules/$(uname -r)/kernel/fs/

过去习惯使用设备文件名然后直接用该文件名挂载,不过近期以来比较建议使用UUID来识别文件系统,会比设备名称与标头名称还要更可靠,因为是独一无二的。

  • 挂载 xfs/ext4/vfat等文件系统
blkid /dev/vda4
(找出UUID后)
mount UUID = “...(略)” /data/xfs
  • 挂载CD或DVD光盘
blkid 
(找出UUID后)
mount /dev/sr0 /data/xfs

光驱一挂载之后就无法退出光盘了,除非你将它卸载才能够退出。

  • 挂载vfat中文移动磁盘(USB磁盘)

类似于前面的CD或DVD光盘

  • 重新挂载根目录与挂载不特定目录

整个目录树最重要的地方就是根目录,所以根目录根本就不能够被卸载。问题是,如果你的挂载参数要改变或是根目录出现【只读】状态时,如何重新挂载?最可能的处理方法就是重新启动(reboot)。不过你也可以这样做:

//将/重新挂载,并加入参数为rw与auto
mount -o remount,rw,auto /

重点是那个【-o remount,xx】的选项与参数。

另外,我们也可以利用mount来将某个目录挂载到另外一个目录。这并不是挂载文件系统,而是额外挂载某个目录的方法。虽然下面的方法也可以使用符号链接来做链接,不过在某些不支持符号链接的程序运行中,还是要通过这样的方法才行。

mount --bind /var /data/var

通过这个mount --bind的功能,您可以将某个目录挂载到其他目录,而并不是整个文件系统,所以从此进入/data/var就是进入/var的意思。

  • umount(将设备文件卸载)
umount [-fn] 设备文件名或挂载点

选项与参数:

- -f : 强制卸载,可用在类似网络文件系统(NFS)无法读取到的情况下;

- -l : 立即卸载文件系统,比-f还强;

- -n : 不更新/etc/mtab情况下卸载。

就是直接将已经挂载的文件系统卸载,卸载之后,可以使用df或mount看看是否还存在于目录树中。卸载的方式,可以输入设备文件名或挂载点,均可接受。

7.3.6 磁盘/文件系统参数自定义-pg246

  • mknod

通过文件的major与minor数值来代表设备,常见的磁盘文件名和代码如下:

磁盘文件名majorminor
/dev/sda80-15
/dev/sdb816-31
/dev/loop070
/dev/loop171
mknod 设备文件名 [bcp] [Major] [Minor]

选项与参数:

设备种类:

- b : 设置设备名称成为一个外接存储设备文件,例如磁盘等;
- c : 设置设备名称成为一个外接输入设备文件,例如鼠标/键盘等;
- p : 设置设备名称成为一个FIFO文件。

Major : 主要设备代码;

Minor : 次要设备代码。

  • xfs_admin修改XES文件系统的UUID与Label name
xfs_admin [-lu] [-L label] [-U uuid] 设备文件名

选项与参数:

- -l : 列出这个设备的labei name;
- -u : 列出这个设备的UUID;
- -L : 设置这个设备的Label name;
- -U : 设置这个设备的UUID。
  • tune2fs修改ext4的label name与UUID
tune2fs [-l] [-L label] [-U uuid] 设备文件名

选项与参数:

- -l : 类似dump2fs -h的功能,将superblock内的数据读出来;
- -L : 修改LABEL name;
- -U : 修改UUID。

7.4 设置启动挂载

7.4.1 启动挂载/etc/fstab及/etc/mtab-pg248

挂载的一些限制:

  • 根目录 / 是必须挂载的,而且一定要先于其他挂载点(mount point)被挂载进来;
  • 其他挂载点必须为已建立的目录,可任意指定,但一定要遵守必须的系统目录架构原则(FHS);
  • 所有挂载点在同一时间之内,只能挂载一次;
  • 所有磁盘分区在同一时间之内,只能挂载一次;
  • 如若进行卸载,您必须先将工作目录移到挂载点(及其子目录)之外。

以/etc/fstab为例

cat /etc/fstab

输出六栏,一定要背下来,如下:

[设备/UUID等] [挂载点] [文件系统] [文件系统参数] [dump] [fsck]

  • 第一栏:磁盘设备文件名/UUID/LABEL name,主要有三个项目

    • 文件系统或磁盘的设备文件名,如/dev/vda2等;
    • 文件系统的UUID名称,如UUID=xxx;
    • 文件系统的LABEL名称,例如LABEL=xxx。
  • 第二栏:挂载点(mount point)

挂载点一定是目录。

  • 第三栏:磁盘分区的文件系统

在手动挂载时可以让系统自动测试挂载,但在这个文件当中我们必须要手动写入文件系统才行,包括xfs、ext4,vfat、reiserfs、nfs等。

  • 第四栏:文件系统参数
参数内容意义
async/sync
异步/同步
设置磁盘是否以异步方式运行,默认为async(性能较佳)。
auto/noauto
自动/非自动
当执行mount -a时,此文件系统是否会被主动测试挂载,默认为auto。
rw/ro
可擦写/只读
让该分区以可读写或只读的状态挂载上来,如果你想要分享的数据是不给用户随意变更,这里也能够设置为只读,则不论在此文件系统的文件是否设置w权限,都无法写入。
exec/noexec
可执行/不可执行
限制在此文件内是否可以进行【执行】的工作?如果是纯粹用来存储数据的目录,那么可以设置为noexec会比较安全。不过,这个参数也不能随便使用,因为你不知道该目录下是否默认会有执行文件。
user/nouser
允许/不允许用户挂载
是否允许用户使用mount命令来挂载?一般而言,我们当然不希望一般身份的user能使用mount,因为太不安全了,因此这里应该设置为nouser。
suid/nosuid
具有/不具有suid权限
该文件系统是否允许SUID的存在?如果不是执行文件放置目录,也可以设置为nosuid来取消这个功能。
defaults同时具有rw、suid、dev、exec、auto、nouser、async等参数,基本上,默认情况使用defaults设置即可。
  • 第五栏:能否被dump备份命令作用

dump是一个用来作为备份的命令,不过现在有太多的备份方案,所以这个项目可以不要理会,直接输入0就好。

  • 第六栏:是否以fsck检验扇区

早期启动的流程中,会有一段时间去检验本机的文件系统,看着文件系统是否完整(clean)。不过这个阶段主要是通过fsck去完成,我们现在用的xfs文件系统就没有办法适用,因为xfs会自己进行检验,不需要额外进行这个操作,所以直接填0就好了。

实际文件系统的挂载是记录到/etc/mtab与/proc/mounts这两个文件中的。

7.4.2 特殊设备loop挂载(镜像文件不刻录就挂载使用)-pg251

  • 挂载CD/DVD镜像文件
mount -o loop /temp/xx /xx

主要是用loop命令进行挂载。


7.5 内存交换分区(swap)之创建

安装Linux时一定需要的两个硬盘分区,一个是根目录,另外一个是内存交换分区。

可以使用如下方法来建立内存交换分区:

  • 设置一个内存交换分区;
  • 建立一个虚拟内存的文件。

7.5.1 使用物理分区创建内存交换分区-pg253

步骤:

  1. 分区:先使用gdisk在你的磁盘中划分出一个分区给系统作为内存交换分区,由于Linux的gdisk默认会将分区的ID设置为Linux的文件系统,所以你可能还得要设置一下system ID;
  2. 格式化:利用建立内存交换分区格式的【mkswap 设备文件名】就能够格式化该分区成为内存交换分区格式;
  3. 使用:最后将该swap设备启动,方法为【swapon 设备文件名】;
  4. 观察:最终通过free与swapon -s这个命令来观察一下内存的使用量。

7.5.2 使用文件创建内存交换文件-pg254

  1. 使用dd这个命令在/tmp下面新增一个128MB的文件;
  2. 使用mkswap将/tmp/swap这个文件格式化为内存交换文件的文件格式;
  3. 使用swapon来将/tmp/swap启动;
  4. 使用swapoff关闭swap file,并设置自动启用。

7.6 文件系统的特殊观察与操作

7.6.2 利用GNU的parted进行分区操作(可选)-pg256

parted [设备] [命令[参数]]

选项与参数:

命令功能:

  • 新增分区 : mkpart [primary|logical|Extended] [ext4|vfat|xfs] 开始 结束;
  • 显示分区 : print;
  • 删除分区 : rm[partition]。

#捌、第八章-文件与文件系统的压缩


8.1 压缩文件的用途与技术-pg262

压缩后与压缩的文件所占用的磁盘空间大小,就可以称为是压缩比。


8.2 Linux系统常见的压缩命令

几个常见的压缩文件扩展名:

  • *.z compress程序压缩的文件;
  • *.zip zip程序压缩的文件;
  • *.gz gzip程序压缩的文件;
  • *.bz2 bzip2程序压缩的文件;
  • *.xz xz程序压缩的文件;
  • *.tar tar程序打包的文件,并没有压缩过;
  • *.tar.gz tar程序打包的文件,并且经过gzip的压缩;
  • *.tar.bz2 tar程序打包的文件,并且经过bzip2的压缩;
  • *.tar.xz tar程序打包的文件,并且经过xz的压缩。

8.2.1 gzip,zcat/zmore/zless/zgrep-pg263

gzip可以说是应用最广的压缩命令了,目前gzip可以解开compress、zip与gzip等软件所压缩的文件,至于gzip所建立的压缩文件为*.gz。

gzip [-cdtv#] 文件名
zcat 文件名.gz

选项与参数:

  • -c : 将压缩的数据输出到屏幕上,可通过数据流重定向来处理;
  • -d : 解压缩的参数;
  • -t : 可以用来检验一个压缩文件的一致性,看着文件有无错误;
  • -v : 可以显示出原文件/压缩文件的压缩比等信息;
  • -# : #为数字的意思,代表压缩等级,-1最快,但是压缩比最差,-9最慢,但是压缩比最好,默认是-6。

当你使用gzip进行压缩时,在默认的状态下原本的文件会被压缩成为.gz后缀的文件,源文件就不再存在了。

cat/more/less可以使用不同的方式来读取纯文本文件,那个zcat/zmore/zless则可以对应于cat/more/less的方式来读取纯文本文件被压缩后的压缩文件。

8.2.2 bzip2,bzcat/bzmore/bzless/bzgrep-pg265

bzip2是为了替换gzip并提供更佳的压缩比。

bzip2 [-cdkzv#] 文件名
bzcat 文件名.bgz

选项与参数:

  • -c : 将压缩的过程产生的数据输出到屏幕上;
  • -d : 解压缩的参数;
  • -k : 保留原始文件,而不会删除原始的文件;
  • -z : 压缩的参数(默认值,可以不加);
  • -v : 可以显示出原文件/压缩文件的压缩比等信息;
  • -# : 与gzip同样的,都是计算压缩比的参数,-9最佳,-1最快。

8.2.3 xz,xzcat/xzmore/xzless/xzgrep-pg265

xz这个压缩比更高。

xz [-dtlkc#] 文件名
xcat 文件名.xz

选项与参数:

  • -d : 就是解压缩;
  • -t : 测试压缩文件的完整性,看有没有错误;
  • -l : 列出压缩文件的相关信息;
  • -k : 保留原来的文件不删除;
  • -c : 同样的,就是将数据在屏幕上输出的意思;
  • -# : 同样的,也有较佳的压缩比的意思。

8.3 打包命令:tar-pg266

tar [-z|-j|-J] [cv] [-f 待建立的新文件名] filename...   (打包与压缩)
tar [-z|-j|-J] [tv] [-f 既有的tar文件名]               (查看文件名)
tar [-z|-j|-J] [xv] [-f 既有的tar文件名] [-C 目录]      (解压缩)

选项与参数:

  • -c : 建立打包文件,可搭配 -v 来查看过程中被打包的文件名(filename);
  • -t : 查看打包文件的内容含有哪些文件名,重点在查看【文件名】;
  • -x : 解包或解压缩的功能,可以搭配 -C(大写) 在特定目录解压,特别留意的是,-c、-t、-x不可同时出现在一串命令行中;
  • -z : 通过gzip的支持进行压缩/解压缩;此时文件名最好为 *.tar.gz;
  • -j : 通过bzip2的支持进行压缩/解压缩;此时文件名最好为 *.tar.bz2;
  • -J : 通过xz的支持进行压缩/解压缩;此时文件名最好为 *.tar.xz,特别留意,-z、-j、-J不可以同时出现在一串命令行中;
  • -v : 在压缩/解压缩的过程中,将正在处理的文件名显示出来;
  • -f filename :-f 后面要立刻接要被处理的文件名,建议 -f 单独写一个选项。(比较不会忘记)
  • -C 目录 : 这个选项用在解压缩,若要在特定目录解压缩,可以使用这个;
  • -p(小写) : 保留备份数据的原本权限与属性,常用于备份(-c)重要的配置文件;
  • -P(大写) : 保留绝对路径,亦即允许备份数据中含有根目录存在之意;
  • –exclude=FILE : 在压缩的过程中,不要将FILE打包。

最简单的tar命令:

  • 压缩 : tar -jcv -f filename.tar.bz2 要被压缩的文件或目录名称;
  • 查询 : tar -jtv -f filename.tar.bz2;
  • 解压缩 : tar -jxv -f filename.tar.bz2 -C 欲解压缩的目录。

如果仅是打包而已,就是【tar -cv -f file.tar】而已,这个文件我们称为**tarfile,如果还有进行压缩的支持,例如【tar -jcv -f file.tar.bz2】时,我们称为tarball**。

特殊应用:

在tar使用中,有一种方式最特殊,那就是通过标准输入输出的数据流重定向(standard input/standard output),以及管道命令(pipe)的方式,将待处理的文件一边打包一边解压缩到目标目录。


8.4 XFS文件系统的备份与还原

8.4.1 XFS文件系统备份xfsdump-pg272

xfsdump的功能很强,除了可以进行文件系统的完整备份(full backup)之外,还可以进行增量备份(incremental backup)。

第一次备份一定是完整备份,完整备份在xfsdump当中被定义为level0。等到第二次备份时,/home文件系统内的数据已经与level0不一样了,而level1仅只是比较目前的文件系统与level0之间的差异后,备份有变化过的文件。

使用xfsdump时,请注意下面的限制:

  • xfsdump不支持没有挂载的文件系统备份,所以只能备份已挂载的文件系统;
  • xfsdump必须使用root的权限才能操作(涉及文件系统的关系);
  • xfsdump只能备份xfs文件系统;
  • xfsdump备份下来的数据(文件或存储媒介)只能让xfsrestore解析;
  • xfsdump是通过文件系统的UUID来辨别各备份文件,因此不能备份两个具有相同UUID的文件系统。
xfsdump [-L S_label] [-M M_label] [-l #] [-f 备份文件] 待备份数据
xfsdump -I

选项与参数:

  • -L : xfsdump会记录每次备份的session标头,这里可以填写针对此文件系统的简易说明;
  • -M : xfsdump可以记录存储媒介的标头,这里可以填写此媒介的简易说明;
  • -l : 是L的小写,就是指定等级,有0-9共10个等级。(默认是0,即完整备份);
  • -f : 有点类似tar,后面接产生的文件,亦可接例如/dev/st0设备文件名或其他一般文件文件名等;
  • -I : 从/var/lib/xfsdump/inventory列出目前备份的信息状态。

进行增量备份时,一定要进行过完整备份后(-l 0)才能够继续有其他增量备份(-l 1~9)的能力。

8.4.2 XFS文件系统还原xfsrestore-pg275

备份文件在急用时可以恢复系统的重要数据,xfsdump的恢复使用的是xfsrestore这个命令。

xfsrestore -I											(用来查看备份文件)
xfsrestore [-f 备份文件] [-L S_label] [-s] 待恢复目录		(单一文件全系统恢复)
xfsrestore [-f 备份文件] -r 待恢复目录						(通过增量备份文件来恢复系统)
xfsrestore [-f 备份文件] -i 待恢复目录						(进入交互模式)

选项与参数:

  • -I : 跟xfsdump相同的输出,可查询备份数据,包括Label名称与备份时间等;
  • -f : 后面接的就是备份文件,企业界很有可能会接/dev/st0等磁带机,我们这里接文件名;
  • -L : 就是session的Label name,可用-I查询到的数据,在这个选项后输入;
  • -s : 需要接某特定目录,亦即仅恢复某一个文件或目录之意;
  • -r : 如果用文件来存储备份数据,则不需要使用,如果是一个磁带内有多个文件,需要此选项来完成累积恢复;
  • -i : 进入交互模式,高级管理员使用的,一般我们不太需要操作它。

8.5 光盘写入工具

通常的做法是:

  • 先将所需要备份的数据创建一个镜像文件(iso),利用mkisofs命令来处理;
  • 将该镜像文件刻录至CD或DVD当中,利用cdrecord命令来处理。

8.5.1 mkisofs:建立镜像文件-pg277

利用一般数据光盘镜像文件,mkisofs的使用方法如下:

mkisofs [-o 镜像文件] [-Jrv] [-V vol] [-m file] 待备份文件... -graft-point isodir=systemdir ...

选项与参数:

  • -o : 后面接你想要产生的那个镜像文件;
  • -J : 产生较兼容Windows的文件名结构,可增加文件名长度到64个unicode字符;
  • -r : 通过Rock Ridge产生支持UNIX/Linux的文件数据,可记录较多的信息(如UID/GID等);
  • -v : 显示创建ISO文件的过程;
  • -V vol : 建立Volume,有点像WIndows在文件系统管理器内看到的CD卷标;
  • -m file : -m 为排除文件(exclude)的意思,后面的文件不备份到镜像文件中,也能使用 * 通配符;
  • -graft-point : graft 有转嫁或移植的意思,-graft-point 后面接的就是要备份的数据。

光盘的格式一般称为iso9660,这种格式一般仅支持旧版的DOS文件名,亦即文件名只能以8.3(文件名8个字符,扩展名3个字符)的方式存在。

所有要被加到镜像文件中的文件都会被放置到镜像文件中的根目录,可以利用如下的方法来定义位于镜像文件中的目录:

  • 镜像文件中的目录所在等于实际Linux文件系统的目录所在;
  • /movies/=/srv/movies/(在Linux的/srv/movies内的文件,加至镜像文件中的/linux/etc/目录);
  • /linux/etc=/etc(将Linux中的/etc/内的所有数据备份到镜像文件中的/linux/etc/目录)。

8.5.2 cdrecord:光盘刻录工具-pg280

wodim被链接到cdrecord中,建议还是改用wodim比较干脆。

wodim --devices dev=/dev/sr0...				(查询刻录机的bus位置)
wodim -v dev=/dev/sr0 black=[fast|all]		(抹除重复读写盘)
wodim -v dev=/dev/sr0 -format				(格式化DVD+RW)
wodim -v dev=/dev/sr0 [可用选项功能] file.iso	

选项与参数:

  • –devices : 用在扫描磁盘总线并找出可用的刻录机,后续的设备为ATA接口;

  • -v : 在cdrecord运行的过程中显示过程;

  • dev=/dev/sr0 : 可以找出此光驱的bus地址,非常重要;

  • black=[fast|all] : black为抹除可重复写入的CD/DVD-RW这种格式的DVD而已;

  • -format : 对光盘进行格式化,但是仅针对DVD+RW这种格式的DVD而已。

  • [可用选项功能]主要是写入CD/DVD时可使用的选项,常见的选项包括有:

    • -data : 指定后面的文件以数据格式写入,不是以CD音频(-audio)方式写入;
    • speed=X : 指定刻录速度,例如CD可用speed=40为40倍数,DVD则可用speed=4之类;
    • -eject : 指定刻录完毕后自动推出光盘;
    • fs=Ym : 指定缓冲内存大小,可用在将镜像文件先暂存至缓冲内存,默认是4m,一般建议可增加到8m,不过,还是得视刻录机而定。
  • 针对DVD的选项功能:

    • driveropts=burnfree : 打开Buffer Underrun Free模式的写入功能;
    • ssc : 支持DVD-RW的模式。

8.6 其他常见的压缩与备份工具

8.6.1 dd-pg282

dd最大的功能在于备份,因为dd可用读取磁盘设备的内容(几乎是直接读取扇区),然后将整个设备备份成一个文件。

dd if="input_file" of="output_file" bs="block_size" count="number"

选项与参数:

  • if : 就是input file,也可以是设备;
  • of : 就是output file,也可以是设备;
  • bs : 设置的一个block的大小,若未指定则默认是512Bytes(一个扇区的大小);
  • count : 多少个bs的意思。

8.6.2 cpio-pg284

一般来说,cpio要配合类似find等可以查找文件的命令来告知cpio该被备份的数据在哪里。

cpio -ovcB > [file|device]		(备份)
cpio -ivcdu < [file|device]		(还原)
cpio -ivct < [file|device]		(查看)

选项与参数:

  • 备份会用到的:

    • -o : 将数据复制输出到文件或设备上;
    • -v : 让存储的过程中文件名称可以在屏幕上显示;
    • -c : 一种较新的portable format方式存储;
    • -B : 让默认的blocks可以增加至5120字节,默认是512字节。这样的好处是可以让大文件的存储速度加快。
  • 还原会用到的:

    • -i : 将数据自文件或设备复制出来到系统当中;
    • -v : 让存储的过程中文件名称可以在屏幕上显示;
    • -c : 一种较新的portable format方式存储;
    • -d : 自动建立目录,使用cpio所备份的内容不见得会在同一层目录中,因此必须要让cpio在还原时可以建立新目录,此时就得要 -d 选项的帮助;
    • -u : 自动的将较新的文件覆盖较旧的文件。
  • 查看会用到的:

    • -i : 将数据自文件或设备复制出来到系统当中;
    • -v : 让存储的过程中文件名称可以在屏幕上显示;
    • -c : 一种较新的portable format方式存储;
    • -t : 需要配合 -i 选项,可用在“查看”以cpio建立的文件或设备的内容。

第三部分 学习shell与shell script


玖、第九章-vim程序编辑器


9.1 vi与vim

为何要学vim,因为:

  • 所有的UNIX-like系统都会内置vi文本编辑器,其他的文本编辑器则不一定会存在;
  • 很多软件的编辑接口都会主动调用vi(例如未来会谈到的crontab等命令);
  • vim具有程序编辑的能力,可以主动地以字体颜色辨别语法的正确性,方便程序设计;
  • 因为程序简单,编辑速度相对快速。

9.2 vi的使用

基本上,vi的使用分为三种模式,分别是一般命令模式、编辑模式与命令行模式。作用分别是:

  • 一般命令模式(command mode)

    以vi打开一个文件就直接进入一般命令模式(简称一般模式)了。在这个模式中,你可以使用【上下左右】按键来移动光标,可以使用【删除字符】或【删除整行】来处理文件内容,也可以使用【复制、粘贴】来处理你的文件内容。

  • 编辑模式(insert mode)

    在一般模式中可以进行删除、复制、粘贴等的操作,但是却无法编辑文件的内容。要等到按下【i、l、o、O、a、A、r、R】等任何一个字母之后才会进入编辑模式。注意了,通常在Linux中,按下这些按键时,在界面的左下方会出现【INSERT】或【REPLACE】的字样,此时才可以进行编辑,而如果要回到一般模式时,则必须按下【Esc】这个按键即可退出编辑模式。

  • 命令行模式(command-line mode)

    在一般模式中,输入【: / ?】三个中的任意一个按钮,就可以将光标移动到最下面那一行。在这个模式当中,可以提供你【查找数据】的操作,而读取、保存、批量替换字符、退出vi、显示行号等操作则是在此模式中完成的。

9.2.1 简易执行范例-pg292

如果你想要使用vi来建立一个名为welcome.txt的文件时,你可以这样做:

    1. 使用【vi filename】进入一般命令模式
/bin/vi welcome.txt
    1. 按下i进入编辑模式,开始编辑文字

在一般模式之中,只要按下i、o、a等字符就可以进入编辑模式了,在编辑模式当中,你可以发现在左下角状态栏中会出现-INSERT-的字样,那就是可以输入任何字符的提示。这个时候,键盘上除了[Esc]这个按键之外,其他的按键都可以视作一般的输入按钮,所以你可以进行任何的编辑。

    1. 按下[Esc]回到一般命令模式

按下[Esc]这个按键,你会发现-INSERT-不见了。

    1. 进入命令行模式,文件保存并退出vi环境

保存(write)并退出(qiut)的命令很简单,输入【:wq】即可保存退出。

9.2.2 按键说明-pg293

  • 第一部分:一般命令模式可用的功能按键说明、光标移动、复制粘贴、查找替换等
移动光标的方法
h或向左箭头键(←)光标向左移动一个字符
j或向左箭头键(↓)光标向下移动一个字符
k或向左箭头键(↑)光标向上移动一个字符
l或向左箭头键(→)光标向右移动一个字符
如果要多次移动,例如向下移动30行,可以使用30j或30↓
[Ctrl]+[f]屏幕【向下】移动一页,相当于[Page Down]按键(常用)
[Ctrl]+[b]屏幕【向上】移动一页,相当于[Page Up]按键(常用)
[Ctrl]+[d]屏幕【向下】移动半页
[Ctrl]+[u]屏幕【向上】移动半页
+光标移动到非空格符的下一行
-光标移动到非空格符的上一行
n(n加空格键)那个n表示【数字】,按下数字再按下空格键,光标会向右移动这一行的n个字符,例如20这样
0或功能键[Home]数字【0】,移动到这一行的最前面字符处(常用)
$或功能键[End]移动到这一行的最后面字符处(常用)
H光标移动到这个屏幕的最上方那一行的第一个字符
M光标移动到这个屏幕的中央那一行的第一个字符
L光标移动到这个屏幕的最下方那一行的第一个字符
G光标移动到这个文件的最后一行(常用)
nGn为数字,移动到这个文件的第n行
gg移动到这个文件的第一行,相当于1G(常用)
n(n加Enter键)那个n表示【数字】,按下数字再按下Enter键,光标向下移动n行(常用)
查找与替换
/word向光标之下寻找一个名称为word的字符串,word可以换成其他的字符串
?word向光标之上寻找一个名称为word的字符串,word可以换成其他的字符串
n这个n是英文按键,代表【重复前一个查找的操作】。
N这个N是英文按键,与n相反,代表【反向前一个查找的操作】。
使用/word配合n及N是非常有帮助的,可以让你重复的找到一些你查找的关键词。
:n1,n2s/word1/word2/gn1与n2为数字,在第n1与n2行之间寻找word1这个字符串,并将该字符串替换为word2。(常用)
:1,$s/word1/word2/g从第一行到最后一行寻找word1这个字符串,并将该字符串替换为word2。(常用)
:1,$s/word1/word2/gc从第一行到最后一行寻找word1这个字符串,并将该字符串替换为word2,且在替换前显示提示符给用户确认(confirm)是否需要替换。
删除、复制与粘贴
x与X在一行当中,x为向后删除一个字符(相当于[del]按键),X为向前删除一个字符(相当于[Backspace]即退格键)。(常用)
nxn为数字,连续向后删除n个字符。(常用)
dd删除(剪切)光标所在的那一整行。(常用)
nddn为数字,删除(剪切)光标所在的向下n行。(常用)
d1G删除(剪切)光标所在到第一行的所有数据。
dG删除(剪切)光标所在到最后一行的所有数据。
d$删除(剪切)光标所在处,到该行的最后一个字符。
d0那个是数字0,删除(剪切)光标所在处,到该行的最前面一个字符。
yy复制光标所在的那一行。(常用)
nyyn为数字,复制光标所在的向下n行。(常用)
y1G复制光标所在到第一行的所有数据。
yG复制光标所在到最后一行的所有数据。
y0那个是数字0,复制光标所在的那个字符到该行行首的所有数据。
y$复制光标所在的那个字符到该行行尾的所有数据。
p与Pp为将已复制的数据在光标下一行粘贴,P则为贴在光标上一行。(常用)
J将光标所在行与下一行的数据结合成同一行。
c重复删除多个数据。例如向下删除10行(10cj)。
u恢复前一个操作。(常用)
[Ctrl]+r重做上一个操作。(常用)
.这就是小数点,重复前一个操作。(常用)
  • 第二部分:一般命令模式切换到编辑模式的可用的按键说明
进入插入或替换的编辑模式
i与l进入插入模式(Insert mode):
i为【从目前光标所在处插入】,l为【在目前所在行的第一个非空格符处开始插入】。(常用)
a与A进入插入模式(Insert mode):
a为【从目前光标所在的下一个字符处开始插入】,A为【从光标所在行的最后一个字符处开始插入】。(常用)
o与O进入插入模式(Insert mode):
这是英文字母o的大小写,o为【从目前光标所在的下一行处开始插入】,O为【在目前光标所在处的上一行插入新的一行】。(常用)
r与R进入插入模式(Insert mode):
r为【只会替换光标所在的那一个字符一次】,R为【会一直替换光标所在的文字,直到按下Esc为止】。(常用)
上面那些按键中,在vi界面的左下角会出现【--INSERT——】或【--REPLACE--】的字样。
[Esc]退出编辑模式,回到一般命令模式。(常用)
  • 第三部分:一般命令模式切换到命令行模式的可用的按键说明
命令行模式的保存、退出等命令
:w将编辑的数据写入硬盘文件中。(常用)
:w!若文件属性为【只读】时,强制写入该文件。不过,到底能不能写入,还是跟你对接文件的文件权限有关。
:q退出vi。(常用)
:q!若曾修改文件,又不想保存,使用!为强制出不保存。(常用)
注意一下,那个感叹号(!)在vi当中,常常具有【强制】的意思。
:wq保存后退出,若为:wq!则为强制保存后退出。(常用)
ZZ这是大写的Z,若文件没有修改,则不保存退出,若文件已经被修改过,则保存后退出。
:w[filename]将编辑的数据保存成另一个文件(类似另存新文件)。
:r[filename]在编辑的数据中,读入另一个文件的数据,亦即将【filename】这个文件内容加到光标所在行后面。
:n1,n2w[filename]将n1到n2的内容保存为filename这个文件。
:!command暂时退出vi到命令行模式下执行command的显示结果。例如【:!ls /home】即可在vi当中查看/home下面以ls输出的文件信息。
vim环境的修改
:set nu显示行号,设置之后,会在每一行的前缀显示该行的行号。
:set nonu与set nu相反,为取消行号。

特别注意的是,在vi中,【数字】是很有意义的,数字通常代表重复做几次的意思,也有可能是代表去到第几个什么什么的意思。


9.2 vi的使用-pg299

vim具有颜色显示的功能,并且还支持许多的程序语法(syntax)。

vim还可以直接进行【程序除错(dubug)】的功能。(具体看书的案例)


9.2 vim的额外功能

9.3.1 可视区块(Visual Block)-pg300

自行实验,列举一下按键说明:

可视区块的按键意义
v字符选择,会将光标经过的地方反白选择。
V行选择,会将光标经过的行反白选择。
[Ctrl]+v可视区块,可以用矩形的方式选择数据。
y将反白的地方复制起来。
d将反白的地方删除掉。
p将刚刚复制的区块,在光标所在处粘贴。

9.3.2 多文件编辑-pg301

自行实验,列举一下按键说明:

多文件编辑的按键
:n编辑下一个文件。
:N编辑上一个文件。
:files列出目前这个vim开启的所有文件。

9.3.3 多窗口功能-pg302

如何划分窗口并放入文件?在命令行模式输入【:sp{filename}】即可。如果想要在新窗口启动另一个文件,就加入文件名,否则仅输入:sp时,出现的则是同一个文件在两个窗口间。

多窗口情况下的按键功能。
:sp[filename]打开一个新窗口,如果有加filename,表示在新窗口创建一个新文件,否则表示两个窗口为同一个文件内容(同步显示)。
[ctrl]+w+j
[ctrl]+w+↓
按键的用法是:先按下[ctrl]不放,再按下w后放开所有按键,之后再按下j(或向下箭头键),则光标可移动到下方的窗口。
[ctrl]+w+k
[ctrl]+w+↑
按键的用法是:先按下[ctrl]不放,再按下w后放开所有按键,之后再按下k(或向上箭头键),则光标可移动到上方的窗口。
[ctrl]+w+q其实就是:q结束退出的作用。

9.3.4 vim的关键词补充功能-pg303

主要vim补全功能,大致有下面几个:

组合键补全的内容
[ctrl]+x -> [ctrl]+n通过目前正在编辑的这个【文件的内容文字】作为关键词,予以补齐。
[ctrl]+x -> [ctrl]+f以当前目录内的【文件名】作为关键词,予以补充。
[ctrl]+x -> [ctrl]+o以扩充名作为语法补充,以vim内置的关键词,予以补齐。

9.3.5 vim环境设置与记录:/.vimrc、/.viminfo-pg304

vim会主动地将你曾经做过的操作记录下来,好让你下次可以轻松地作业,这个记录操作的文件就是:~/.viminfo。

如果想了解目前设置的环境设置参数的设置值,可以在一般命令模式时输入【:set all】来查看。

vim的环境设置参数
:set nu
:set nonu
就是设置与取消行号。
:set hlsearch
:set nohlsearch
hlsearch就是high light search(高亮度查找),这个就是设置是否将查找的字符串反白的设置值,默认值是hlsearch。
:set autoindent
:set noautoindent
是否自动缩进?autoindent就是自动缩进。
:set backup是否自动保存备份文件?一般是nobackup的,如果设置backup的话,那么当你修改任何一个文件时,则源文件会被另存为一个文件名为filename~的文件。举例来说,我们编辑hosts,设置:set backup,那么当修改hosts时,在同目录下,就会产生hosts~文件名的文件,记录原始的hosts文件内容。
:set ruler还记得我们提到的右下角的一些状态栏说明?这个ruler就是在显示或不显示该设置值的。
:set showmode这个则是,是否要显示--INSERT--之类的字眼在左下角的状态栏。
:set backspace=(012)一般来说,如果我们按下i进入编辑模式后,可以利用退格键(Backspace)来删除任何字符。但是,某些Linux发行版则不许如此。此时,可以通过backspace来设置,当backspace为2时,就是可以删除任意值;0或1时,仅可删除刚刚输入的字符,而无法删除原本就已经存在的文字。
:set all显示目前所有的环境参数设置值。
:set显示与系统默认值不同的设置参数,一般来说就是你有自行变动过的设置参数。
:syntax on
:syntax off
是否依据程序相关语序显示不同颜色?举例来说,在编辑一个纯文本文件时,如果开头是以#开始,那么该行就会变成蓝色。如果你懂得写程序,那么这个:syntax on还会主动的帮你除错。但是,如果你仅是编写纯文本文件,要避免颜色对你的屏幕产生的干扰,则可以取消这个设置。
:set bg=dark
:set bg=light
可用以显示不同的颜色色调,默认是【light】,如果你常常发现注释的深蓝色实字体在很不容易看,那么这里可以设置为dark,试看看,会有不同的样式。

整体vim的设置值一般是放置在/ect/vimrc这个文件中,不过,不建议你修改它,你可以修改~/.vimrc这个文件(默认不存在,请你自行手动建立),将你所希望的设置值写入。

9.3.6 vim常用命令示意图-pg305

很重要!!!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vVOasmRC-1650619261260)(https://thumbnail0.baidupcs/thumbnail/48e739054k4ca681e3334fa5d430535b?fid=1531607901-250528-531870224381011&time=1648717200&rt=sh&sign=FDTAER-DCb740ccc5511e5e8fedcff06b081203-%2Btwyh3UG%2Fz%2BhHyfLF8Qk2d%2FPtD8%3D&expires=8h&chkv=0&chkbd=0&chkpc=&dp-logid=8998667545598201561&dp-callid=0&file_type=0&size=c710_u400&quality=100&vuk=-&ft=video)]


9.4 其他vim使用注意事项

9.4.1 中文编码的问题-pg306

LANG=zh_CN.gb18030
export LC_ALL=zh_CN.gb18030

然后在终端工具栏的 【终端】 --> 【设置字符编码】 --> 【中文(简体)】 选项点选一下。

9.4.2 DOS与Linux的换行符-pg306

dos2unix [-kn] file [newfile]   //DOS转unix
unix2dos [-kn] file [newfile]	//unix转DOS

选项与参数:

  • -k : 保留该文件原本的mtime时间格式(不更新文件上次内容经过自定义的时间);
  • -n : 保留原本的旧文件,将转换后的内容输出到新文件。

9.4.3 语系编码转换-pg307

iconv --list
iconv -f 原本编码 -t 新编码 filename [-o newfile]

选项与参数:

  • –list : 列出iconv支持的语系数据;
  • -f : from,亦即来源之意,后接原本的编码格式;
  • -t : to,亦即后来的新编码要是什么格式;
  • -o file : 如果要保留原本的文件,那么使用-o新文件名,可以建立新编码文件。

拾、第十章-认识与学习BASH

管理整个计算机硬件的其实就是操作系统的内核(Kernel),这个内核是需要被保护的。


10.1 认识BASH这个shell

10.1.1 硬件、内核与Shell-pg311

我们必须要通过Shell将我们输入的命令与内核沟通,好让内核可以控制硬件来正确无误地工作。

10.1.4 Bash shell的功能-pg314

bash主要的优点如下:

  • 历史命令(history):(查询曾经做过的操作)

    只要在命令行按【上下键】就可以找到前后一个输入的命令。

    这个记录在哪呢?就在家目录内的.bash_history,不过,~/.bash_history记录的是前一次登录以前执行过的命令,而至于这一次登录所执行的命令都被缓存在内存中,当你成功的注销系统后,该命令才会记录到.bash_history当中。

  • 命令与文件补齐功能:([Tab]按键的好处)

    • [Tab]接在一串命令的第一个字后面,则为命令补全;
    • [Tab]接在一串命令的第二个字后面,则为【文件补齐】;
    • 若安装 bash-completion 软件,则在某些命令后面使用[Tab]按键时,可以进行【选项/参数的补齐】功能。
  • 命令别名设置功能:(alias)

    可以直接执行命令来设置命令的别名:

    alias lm = 'ls -al'
    
  • 任务管理、前台、后台控制:(job control、foreground、background)

    后面讲到。

  • 程序化脚本:(shell scripts)

    后面讲到。

  • 通配符:(Wildcard)

    除了完整的字符串之外,bash还支持许多的通配符来帮助用户查询与命令执行。

    举例来说,想知道/usr/bin下面有多少以X为开头的文件,使用【ls -l /usr/bin/X*】。这个*就是通配符。

10.1.5 查询命令是否为Bash shell的内置命令:type-pg315

type 

选项与参数:

  • : 不加任何选项与参数时,type会显示出name是外部命令还是bash内置命令;
  • -t : 当加入-t参数时,type将name以下面这些字眼显示出它的意义:
    • file : 表示为外部命令;
    • alias : 表示该命令为命令别名所设置的名称;
    • builtin : 表示该命令为bash内置的命令功能;
  • -p : 如果后面接的name为外部命令时,才会显示完整文件名;
  • -a : 会由PATH变量定义的路径中,将所有含name的命令都列出来,包含alias。

10.1.6 命令的执行与快速编辑按钮-pg316

组合键功能与示范
[ctrl]+u/[ctrl]+k分别是从光标处向前删除命令串([ctrl]+u)及向后删除命令串([ctrl]+k)
[ctrl]+a/[ctrl]+e分别是让光标移动到整个命令串的最前面([ctrl]+a)或最后面([ctrl]+e)

10.2 Shell的变量功能

10.2.1 什么是变量-pg318

简单的定义:变量就是以一组文字或符号等,来替代一些设置或一串保留的数据。

10.2.2 变量的使用与设置:echo、变量设置规则、unset-pg318

变量在被使用时,前面必须要加上美元符号【$】才行,举例来说,用echo读出变量:

echo $HOME或是echo ${HOME}      //推荐使用后者

在bash当中,当一个变量名称尚未被设置时,默认的内容是【空】

变量的设置规则:

  • 变量与变量内容以一个等号【=】来连接;

  • 等号两边不能直接接空格;

  • 变量名称只能是英文字母与数字,但是开头字符不能是数字;

  • 变量的内容若有空格,可使用双引号【"】或单引号【'】将变量内容结合起来,但

    • 双引号内的特殊字符如$等,可以保留原本的特性;

    • 单引号内的特殊字符则仅为一般字符(纯文本)。

  • 可用转义符【\】将特殊符号(如[Enter]、$、\、空格、'等)变成一般字符;

  • 在一串命令的执行中,还需要借由其他额外的命令所提供的信息时,可以使用反单引号【命令】或【$(命令)】。特别注意,那个`是键盘数字1左边的那个;

  • 若该变量为扩增变量内容时,则可用" 变 量 名 称 " 或 变量名称"或 "{变量}累加内容;

  • 若该变量需要在其他子程序执行,则需要以export来使变量变成环境变量;

  • 通常大写字符为系统默认变量,自行设置变量可以使用小写字符,方便判断(纯粹依照用户兴趣与嗜好);

  • 取消变量的方法为使用unset:【unset 变量名称】。

10.2.3 环境变量的功能-pg322

  • 用env观察环境变量与常见环境变量说明

env是environment(环境)的简写。

- HOME
代表用户的根目录。
- SHELL
告知我们,目前这个环境使用的SHELL是哪个程序?Linux默认使用/bin/bash。
- HISTSIZE
这个与历史命令有关,即我们曾经执行过的命令可以被系统记录下来,而记录的条数则是由这个值来设置的。
- MAIL
当我们使用mail这个命令在收信时,系统会去读取的邮箱文件(mailbox)。
- PATH
就是执行文件查找的路径,目录与目录中间以冒号(:)分割,由于文件的查找是依序由PATH的变量内的目录来查询的,所以,目录的顺序也是重要的。
- LANG
这个重要,就是语序数据,很多信息会用到它。我们中文编码通常是zh_CN.GB2312或是zh_CN.UTF-8。
- RANDOM
这个玩意就是随机数的变量。我们可以通过这个随机数文件相关的变量($RANDOM)来随机取得随机数。在BASH的环境下,这个RANDOM变量的内容,介于0~32767。
如果想使用0~9的随机数数值,则利用declare声明数值类型:
```
declare -i number=$RANDOM*10/32768;echo number
```
  • 用set观察所有环境变量(含环境变量与自定义变量)

基本上,在Linux默认的情况中,使用{大写的字母}来设置的变量一般为系统内定需要的变量。

- PS1:(提示字符的设置)
这是PS1(数字1),这个东西就是我们的命令提示字符。当我们每次按下[Enter]按键去执行某个命令后,最后要再次出现提示字符时,就会主动去读取这个变量值。
- \d:可显示出【星期 月 日】的日期格式,如【Mon Feb 2】;
- \H:完整的主机名;
- \h:仅取主机名在第一个小数点之前的名字;
- \t:显示时间,为24小时格式的【HH:MM:SS】;
- \T:显示时间,为12小时格式的【HH:MM:SS】;
- \A:显示时间,为24小时格式的【HH:MM】;
- \@:显示时间,为12小时格式的【am/pm】格式;
- \u:目前用户的账户名称;
- \v:BASH的版本信息;
- \w:完整的工作目录名称,由根目录写起的目录名称,但根目录会以~替换;
- \W:利用basename函数取得工作目录名称,所以仅会列出最后一个目录名;
- \#:执行的第几个命令;
- \$:提示字符,如果是root时,提示字符为#,否则就是$;
- $(关于本shell的PID):美元符号本身也是个变量。这个东西代表的是目前这个shell的进程号,即所谓的PID(Process ID)。
- ?(关于上个执行命令的返回值):当我们执行某些命令时,这些命令都会返回一个执行后的代码。一般来说,如果成功的执行该命令,则会返回一个0值,如果执行过程发生错误,就会返回错误代码才对,一般就是以非0的数值来替换;
- OSTYPE,HOSTTYPE,MACHTYPE(主机硬件与内核的等级)。
  • export:自定义变量转成环境变量

子进程仅会继承父进程的环境变量,子进程不会继承父进程的自定义变量。

10.2.6 变量键盘读取、数组与声明:read、array、declare-pg327

  • read
read [-pt] variable

选项与参数:

  • -p : 后面可以接提示字符;
  • -t : 后面可以接等待的【秒数】,这个比较有趣,不会一直等待使用者。

read之后不加任何参数,直接加上变量名称,那么下面就会主动出现一个空白行等待你的输入。

  • declare,typeset

declare或typeset是一样的功能,就是声明变量的类型。如果使用declare后面并没有接任何参数,那么bash就会主动的将所有的变量名称与内容通通显示出来,就好像使用set一样。

declare [-aixr] variable

选项与参数:

  • -a : 将后面名为variable的变量定义成为数组(array)类型;
  • -i : 将后面名为variable的变量定义成为整数(integer)类型;
  • -x : 用法与export一样,就是将后面的variable变成环境变量;
  • -r : 将变量设置成为readonly类型,该变量不可被更改内容,也不能unset。

bash对于变量有几个基本的定义:

  • 变量类型默认为字符串,所以若不指定变量类型,则1+2为一个字符串而不是计算式,所以上述第一个执行的结果才会出现那种情况;

  • bash环境中的数值运算,默认最多仅能达到整数状态,所以1/3结果是0。

  • 数组(array)变量类型

数组的设置方式如下:

var[index]=content

index是索引,写数字。

一般来说,建议直接以 ${数组} 的方式来读取,比较正确无误。

10.2.7 与文件系统及程序的限制关系:ulimit-pg329

ulimit [-SHacdfltu] [配额]

选项与参数:

  • -H : hard limit,严格的设置,必定不能超过这个设置的数值;
  • -S : soft limit,警告的设置,可以超过这个设置值,但是若超过则有警告信息;设置上,通常soft会比hard小;
  • -a : 后面不接任何选项与参数,可列出所有的限制额度;
  • -c : 当某些程序发生错误时,系统可能会将程序在内存中的信息写成文件(除错用),这种文件就被称为内核文件(core file),此为限制每个内核文件的最大容量;
  • -f : 此shell可以建立的最大文件容量(一般可能设置为2GB)单位为Kbytes;
  • -d : 程序可使用的最大段内存(segment)容量;
  • -l : 可用于锁定(lock)的内存量;
  • -t : 可使用的最大CPU时间(单位为秒);
  • -u : 单一使用者可以使用的最大进程(process)数量。

10.2.8 变量内容的删除、取代与替换(可选)-pg330

  • 变量内容的删除与替换
变量设置方式说明
${变量#关键词}
${变量##关键词}
若变量内容从头开始的数据符合【关键词】,则将符合的最短数据删除
若变量内容从头开始的数据符合【关键词】,则将符合的最长数据删除
${变量%关键词}
${变量%%关键词}
若变量内容从尾向前的数据符合【关键词】,则将符合的最短数据删除
若变量内容从尾向前的数据符合【关键词】,则将符合的最长数据删除
${变量/旧字符串/新字符串}
${变量//旧字符串/新字符串}
若变量内容符合【旧字符串】则【第一个旧字符串会被新字符串替换】
若变量内容符合【旧字符串】则【全部的旧字符串会被新字符串替换】
  • 变量的测试与内容替换
变量设置方式str没有设置str为空字符串str已设置非为空字符串
var=${str-expr}var=exprvar=var=$str
var=${str:-expr}var=exprvar=exprvar=$str
var=${str+expr}var=var=exprvar=expr
var=${str:+expr}var=var=var=expr
var=${str=expr}str=expr
var=expr
str不变
var=
str不变
var=$str
var=${str:=expr}str=expr
var=expr
str=expr
var=expr
str不变
var=$str
var=${str?expr}expr输出至stderrvar=var=$str
var=${str:?expr}expr输出至stderrexpr输出至stderrvar=$str

10.3 命名别名与历史命令

10.3.1 命令别名设置:alias、unalias-pg334

  • 命名别名
alias lm='ls -al'
  • 命名别名删除
unalias lm

10.3.2 历史命令:history-pg335

history [n]
history [-c]
history [-raw] histfiles

选项与参数:

  • n : 数字,意思是【要列出最近的n条命令行表】的意思;不写就是列出目前内存内的所有history记录;
  • -c : 将目前的shell中的所有history内容全部消除;
  • -a : 将目前新增的history命令新增入histfiles中,若没有加histfiles,则默认写入~/.bash_history;
  • -r : 将histfiles的内容读到目前这个shell的history记录中;
  • -w : 将目前的history记录内容写入histfiles中。
!number
!command
!!

选项与参数:

  • number : 执行第几条命令的意思;
  • command : 由最近的命令向前查找【命令串开头为command】的那个命令,并执行;
  • !! : 就是执行上一个命令(相当于按向上键后,按回车)。

10.4 Bash shell的操作环境

10.4.1 路径与命令查找顺序-pg337

命令运行的顺序:

  1. 以相对/绝对路径执行命令;
  2. 由alias找到该命令来执行;
  3. 由bash内置的(builtin)命令来执行;
  4. 通过$PATH这个变量的顺序查找到的第一个命令来执行。

10.4.3 bash的环境配置环节-pg338

  • login与non-login shell

    • login shell:取得bash时需要完整的登录流程,就称为login shell。
    • non-login shell:取得bash的方式不需要重复登陆的操作。
  • /etc/profile(login shell才读)

这是每个用户登录取得bash时一定会读取的配置文件

- PATH:会根据UID决定PATH变量要不要含有sbin的系统命令目录;
- MAIL:根据账号设置好用户的mailbox到 /var/spool/mail 账号名;
- USER:根据用户的账号设置此变量内容;
- HOSTNAME:根据主机的hostname命令决定此变量内容;
- HISTSIZE:历史命令记录条数,CentOS7.x设置为1000;
- umask:包括root默认为022,而一般用户为002等。
  • /etc/profile.d/*.sh

其实这是个目录内的众多文件。

  • /etc/locale.conf

这个文件是由 /etc/profile.d/lang.sh 调用的,这也是我们决定bash默认使用何种语系的重要配置文件。

  • /usr/share/bash-completion/completions/*

bash的login shell情况下所读取的整体环境配置文件其实只有 /etc/profile。

  • ~/.bash_profile(login shell才会读)

在login shell的bash环境中,所读取的个人偏好配置文件其实主要有三个,分别是:

- ~/.bash_profile
- ~/.bash_login
- ~/.profile
  • source:读入环境配置文件的命令
source 配置文件文件名
. 配置文件文件名

利用source或小数点(.)都可以将配置文件的内容读进来目前的shell环境中。

  • ~/.bashrc(non-login shell会读)

当你取得non-login shell时,该bash配置文件仅会读取~/.bashrc而已。

/etc/bashrc 帮我们的bash定义出下面的定义:

- 根据不同的UID设置umask的值;
- 根据不同的UID设置提示字符(就是PS1变量);
- 调用 /etc/profile.d/*.sh。
  • /etc/man_db.conf

这个文件的内容规范了使用man的时候,man page的路径到哪里去寻找。

  • ~/.bash_history

默认情况下,我们的历史命令就记录在这里。

  • ~/.bash_logout

这个文件则记录了【当我注销bash后,系统再帮我做完什么操作后才离开】的意思。

10.4.4 终端的环境设置:stty、set-pg342

  • stty

stty是setting tty终端的意思。

stty [-a]

选项与参数:

  • -a : 将目前所有的stty参数列出来。

在查询到列表中,如果出现 ^ 表示[Ctrl]那个按键的意思。

几个重要关键词的意义:

- intr:发送一个interrupt(中断)的信号给目前正在run的程序(就是终止);
- qiut:发送一个qiut的信号给目前正在run的程序;
- erase:向后删除字符;
- kill:删除在目前命令行上的所有文字;
- eof:End of file的意思,代表【结束输入】;
- start:在某个程序停止后,重新启动它的output;
- stop:停止目前屏幕的输出;
- susp:送出一个terminal stop的信号给正在运行的程序。
  • set
set [-uvCHhmBx]

选项与参数:

  • -u : 默认不启用,若启用后,当使用未设置变量时,会显示错误信息;
  • -v : 默认不启用,若启用后,当信息被输出前,会先显示信息的原始内容;
  • -x : 默认不启用,若启用后,在命令被执行前,会显示命令内容(前面有++符号);
  • -h : 默认启动,与历史命令有关;
  • -H : 默认启动,与历史命令有关;
  • -m : 默认启动,与任务管理有关;
  • -B : 默认启动,与中括号[]的作用有关;
  • -C : 默认不启用,若使用>等,则若文件存在时,该文件不会被覆盖。

bash默认组合键如下:

组合按键执行结果
Ctrl+C终止目前的命令
Ctrl+D输入结束(EOF),例如邮件结束的时候
Ctrl+M就是回车
Ctrl+S暂停屏幕的输出
Ctrl+Q恢复屏幕的输出
Ctrl+U在提示字符下,将整列命令删除
Ctrl+Z暂停目前的命令

10.4.5 通配符与特殊符号-pg344

在bash的操作环境中还有一个非常有用的功能,那就是通配符(wildcard)。

符号意义
*代表【0个到无穷多个】。
代表【一定有一个】任意字符。
[]同样代表【一定有一个在括号内】的字符(非任意字符)。
[-]若有减号在中括号内时,代表【在编码顺序内的所有字符】。
[^]若中括号内的第一个字符为指数符号(^),那表示【反向选择】。
符号内容
#注释符号:这个最常用被使用在脚本当中,视为说明,在后的数据均不执行。
\转义符:将【特殊字符或通配符】还原成一般字符。
|管道(pipe):分割两个管道命令的符号。
;连续命令执行分隔符:连续性命令的界定。
~用户的家目录。
$使用变量前导符:亦即是变量之前需要加的变量替换值。
&任务管理(job control):将命令变成后台任务。
!逻辑运算意义上的【非】not的意思。
/目录符号:路径分割的符号。
>、>>数据流重定向:输出定向,分别是【替换】与【累加】。
<、<<数据流重定向:输入定向。
''单引号,不具有变量替换的功能($变为纯文本)。
""具有变量替换的功能,($可保留相关功能)。
``两个【`】中间为可以先执行的命令,亦可使用$()。
()在中间为子shell的起始与结束。
{}在中间为命令区块的组合。

10.5 数据流重定向

10.5.1 什么是数据流重定向-pg345

  • standard output与standard error output

简单地说,标准输出指的是命令执行所返回的正确信息,而标准错误输出可理解为命令执行失败后,所返回的错误信息。

数据流重定向的功能,数据流重定向可以将standard output(简称stdout)与standard error output(简称stderr)分别传送到其他的文件或设备,而分别传送所用的特殊字符则如下所示:

- 标准输入(stdin):代码为0,使用 < 或 << ;
- 标准输出(stdout):代码为1,使用 > 或 >> ;
- 标准错误输出(stderr):代码为2,使用 2> 或 2>>  ;

文件的建立方式是:

- 该文件若不存在,系统会自动地将它建立起来;
- 当这个文件存在的时候,那么系统就会先将这个文件内容清空,然后再将数据写入;
- 也就是若以 > 输出到一个已存在的文件中,这个文件就会被覆盖掉。

标准输出:

- 1> : 以覆盖的方法将【正确的数据】输出到指定的文件或设备上;
- 1>> : 以累加的方法将【正确的数据】输出到指定的文件或设备上;
- 2> : 以覆盖的方法将【错误的数据】输出到指定的文件或设备上;
- 2>> : 以累加的方法将【错误的数据】输出到指定的文件或设备上;
  • /dev/null垃圾桶黑洞设备与特殊写法

将正确与错误数据通通写入同一个文件的方法

//将命令的数据全部写入名为list的文件中
find /home -name .bashrc > list 2> list		<==错误
find /home -name .bashrc > list 2>&1		<==正确
find /home -name .bashrc &> list 			<==正确

上述表格第一行错误的原因是,由于两股数据同时写入一个文件,又没有使用特殊的语法,此时两股数据可能会交叉写入该文件内,造成次序的错乱。

一般来说,使用 2>&1 的方式。

  • standard input: < 与 <<

    • < 就是【将原本需要由键盘输入的数据,改由文件内容来替换】的意思;
    • << 就是代表【结束的输入字符】的意思。
cat > catfile << "eof"

代表输入 oef 关键字后,此次输入就结束了。

为何要使用命令输出重定向呢?,因为:

  • 屏幕输出的信息很重要,而且我们需要将它存下来的时候;
  • 后台执行中的程序,不希望它干扰屏幕正常的输出结果时;
  • 一些系统的计划任务命令的执行结果,希望它可以存下来时;
  • 一些执行命令的可能已知错误信息时,想以【2> /dev/null】将它丢掉时;
  • 错误信息与正确信息需要分别输出时。

10.5.2 命令执行的判断根据:;、&&、||-pg348

  • cmd;cmd(不考虑命令相关性的连续命令执行)

  • $?(命令返回值)与&&或||

若前一个命令执行的结果为正确,在Linux下面会返回一个$?=0的值。

命令执行情况说明
cmd1&&cmd21.若cmd1执行完毕且正确执行($?=0),则开始执行cmd2。
2.若cmd1执行完毕且为错误执行($?≠0),则cmd2不执行。
cmd1||cmd21.若cmd1执行完毕且正确执行($?=0),则cmd2不执行。
2.若cmd1执行完毕且为错误执行($?≠0),则开始执行cmd2。

10.6 管道命令(pipe)

管道命令使用的是【|】这个界定符号。

管道命令与【连续执行命令】是不一样的。

这个管道命令【|】仅能处理经由前面一个命令传来的正确信息,也就是标准输出的信息,对于标准错误并没有直接处理的能力。

在每个管道后面接的第一个数据必定是【命令】,而且这个命令必须要能够接受标准输入的数据才行,这样的命令才可为管道命令,主要有两个比较注意的地方:

  • 管道命令仅会处理标准输出,对于标准错误会予以忽略;
  • 管道命令必须要能够接受来自前一个命令的数据成为标准输入继续处理才行。

10.6.1 选取命令:cut、grep-pg351

选取信息通常是针对【一行一行】来分析的。

  • cut
cut -d '分割字符' -f fields		<==用于有特定分割字符
cut -c 字符区间					<==用于排列整齐的信息

选项与参数:

  • -d : 后面接分割字符,与-f一起使用;
  • -f : 根据-d的分割字符将一段信息划分成数段,用-f取出第几段的意思;
  • -c : 以字符(characters)的单位取出固定字符区间。

cut主要的用途在于将同一行里面的数据进行分解,最常使用在分析一些数据或文字数据的时候。

  • grep

cut是将一行信息当中,取出某部分我们想要的,而grep则是分析一行信息,若当中有我们所需要的信息,就将该行拿出来。

grep [-acinv] [--color=auto] '查找字符' filename		

选项与参数:

  • -a : 将二进制文件以文本文件的方式查找数据;
  • -c : 计算找到 ‘查找字符’ 的次数;
  • -i : 忽略大小写的不同,所以大小写视为相同;
  • -n : 顺便输出行号;
  • -v : 反向选择,亦即显示出没有 ‘查找字符’ 内容的那一行;
  • –color=auto : 可以将找到的关键字部分加上颜色的显示。

补充:

  • last

last可以输出[账号/终端/来源/日期时间]的数据,并且是排列整齐的。

last | cut -d ' ' -f 1		

能将每一行的第一个字符串输出来,很6,因为cut是按行处理的,而每一行数据又刚好由空格隔开,因此就能输出每行的第一个字符串

last | grep 'root'

将last中出现root的那些行取出来。

last | grep -v 'root

将last中没有root的那些行取出来。

last |grep 'root' |cut -d ' ' -f1

将last中所有有root的行取出来,并且只要第一列。

10.6.2 排序命令:sort、wc、uniq-pg353

  • sort

sort是很有趣的命令,它可以帮我们进行排序,而且可以根据不同的数据形式来排序。

sort [-fbMnrtuk] [file or stdin] 	

选项与参数:

  • -f : 忽略大小写的差异,例如A与a视为编码相同;

  • -b : 忽略最前面的空格字符部分;

  • -M : 以月份的名字来排序,例如JAN、DEC等的排序方法;

  • -n : 使用【纯数字】进行排序(默认是以文字形式来排序的);

  • -r : 反向排序;

  • -u : 就是uniq,相同的数据中,仅出现一行代表;

  • -t : 分割符号,默认是用[Tab]键来分割;

  • -k : 以哪个区间(filed)来进行排序的意思。

  • uniq

排序完成,将重复的数据仅列出一个显示。

uniq [-ic] 

选项与参数:

  • -i : 忽略大小写字符的不同;

  • -c : 进行计数。

  • wc

计算输出信息的整体数据。

wc [-lwm] 

选项与参数:

  • -l : 仅列出行;
  • -w : 仅列出多少字(英文字母);
  • -m : 多少字符。

补充:

  • last

last可以输出[账号/终端/来源/日期时间]的数据,并且是排列整齐的。

last | cut -d ' ' -f1 |sort|uniq

将排序后的数据只取出一行来。

last | cut -d ' ' -f1|sort|uniq -c

统计出每行出现的次数(相当于group by加count)

10.6.3 双向重定向:tee-pg354

tee会同时将数据流分送到文件与屏幕(screen),而输出到屏幕的,其实就是stdout,那就可以让下个命令继续处理。

  • tee
tee [-a] file

选项与参数:

  • -a : 以累加(append)的方式,将数据加入file当中。

补充:

  • last

last可以输出[账号/终端/来源/日期时间]的数据,并且是排列整齐的。

last | tee last.list|cut -d " " -f1

tee是双重导向的分流命令,可以同时将数据流既送到文件屏幕一份,又保存到last.list文件中一份。

10.6.4 字符转换命令:tr、col、jion、paste、expand-pg354

  • tr

tr可以用来删除一段信息当中的文字,或是进行文字信息的替换。

tr [-ds] SET1 ...

选项与参数:

  • -d : 删除信息当中的SET1这个字符;
  • -s : 替换掉重复的字符。

补充:

  • last

last可以输出[账号/终端/来源/日期时间]的数据,并且是排列整齐的。

last | tr [a-z] [A-Z]

将last输出的信息中的小写转换成大写。

使用[]可以设置一串字,也常常用来替换文件中的怪异符号。

  • col
col [-xb]

选项与参数:

  • -x : 将tab键转换成对等的空格键。

虽然col有它特殊的用途,不过,很多时候,它可以用来简单地处理将[tab]按键替换成为空格键。

  • join

join看字面上的意义(加入/参加)就可以知道,它是在处理两个文件之间的数据,而且,主要是在处理【两个文件当中,有相同数据的那一行,才把它加在一起】的意思。

join [-ti12] file1 file2

选项与参数:

  • -t : join默认以空格字符分隔数据,并且比对【第一个栏位】的数据,如果两个文件相同,则将两条数据连成一行,且第一个栏位放在第一个;
  • -i : 忽略大小写的差异;
  • -1 : 这个是数字1,代表【第一个文件要用哪个栏位来分析】的意思;
  • -2 : 代表【第二个文件要用哪个栏位来分析】的意思。

在使用join之前,你所需要处理的文件应该要事先经过排序(sort)处理。

  • paste

paste就是直接将两行贴在一起,且中间以[Tab]键隔开。

paste [-d] file1 file2

选项与参数:

  • -d : 后面可以接分割字符,默认是以[Tab]来分隔;

    • : 如果file部分写成 - ,表示来自标准输入的数据的意思。
  • expand

就是在将[Tab]按键转成空格键。

expand [-t] file

选项与参数:

  • -t : 后面可接数字,一般来说一个Tab按键可以用8个空格键替换,我们也可以自行定义一个[Tab]按键代表多少个字符。

10.6.5 划分命令:split-pg357

  • split
split [-bl] file PREFIX

选项与参数:

  • -b : 后面可接欲划分成的文件大小,可加单位,比如b、k、m等;
  • -l : 以行数来进行划分;
  • PREFIX : 代表前缀字符的意思,可作为划分文件的前缀文字。

10.6.6 参数代换:xargs-pg358

xargs是在做什么?就以字面的意义来看,x是加减乘除的乘号,args则是arguments(参数)的意思。所以说,这个玩意儿就是在产生某个命令的参数的意思。

  • xargs
xargs [-0epn] command

选项与参数:

  • -0 : 如果输入的stdin含有特殊字符,例如`、\、空格等字符时,这个-0参数可以将它还原成一般字符,这个参数可以用于特殊状态。
  • -e : 这是EOF(end of file)的意思,后面可以接一个字符,当xargs分析到这个字符时,就会停止工作;
  • -p : 在执行每个命令时,都会询问使用者的意思;
  • -n : 后面接次数,每次command命令执行时,要使用几个参数的意思。

当xargs后面没有接任何的命令时,默认是以echo来输出。

要使用xargs的原因是,很多命令其实并不支持管道命令,因此我们可以通过xargs来提供该命令使用 标准输入。

10.6.7 关于减号【-】的用途-pg359

在管道命令当中,常常会使用到前一个命令的stdout作为这次的stdin,某些命令需要用到文件名(例如tar)来进行处理时,该stdout与stdin可以利用减号"-"来替代。


拾壹、第十一章-正则表达式与文件格式化处理


11.1 开始之前-pg363

简单来说,正则表达式(Regular Expression,或称为常规表示法)就是处理字符串的方法,它以行为单位来进行字符串的处理操作,正则表达式通过一些特殊符号的辅助,可以让用户轻易地完成【查找、删除、替换】某特定字符串的处理过程。

正则表达式基本上是一种【表示法】,只要程序支持这种表示法,那么该程序就可以用来作为正则表达式的字符串处理之用。

正则表达式的字符串表示方式依照不同的严谨度分为:基础正则表达式与扩展正则表达式。扩展正则表达式除了简单的一组字符串处理之外,还可以作群组的字符串处理。


11.2 基础正则表达式

对字符排序有影响的语系数据就会对正则表达式的结果有影响。

11.2.1 语系对正则表达式的影响-pg365

使用正则表达式时,需要特别留意当时环境的语系是什么,否则可能会发现与别人不相同的选取结果。

下面使用**【LANG=C】**这个语系来进行。

特殊符号代表意义
[:alnum:]代表英文大小写字符及数字,亦即0-9、A~Z、a~z
[:alpha:]代表任何英文大小写字符,亦即A~Z、a~z
[:blank:]代表空格键与[Tab]按键两者
[:cntrl:]代表键盘上面 控制按键,包括CR、LF、Tab、Del等
[:digit:]代表数字而已,即0-9
[:graph:]除了空格符(空格键与[Tab]按键)外的其他所有按键
[:lower:]代表小写字符,即a~z
[:print:]代表任何可以被打印出来的字符
[:punct:]代表标点符号(punctuation symbol),亦即:"'?!;:#$
[:upper:]代表大写字符,即A~Z
[:space:]代表会产生空白的字符,包括空格键、[Tab]、CR等
[:xdigit:]代表十六进制的数字类型,因此包括0-9、A~F、a~f的数字字符

11.2.2 grep的一些高级选项-pg365

  • grep
grep [-A] [-B] [--color=auto] '查找字符' filename

选项与参数:

  • -A : 后面可加数字,为after的意思,除了列出该行外,后面的n行也列出来;
  • -B : 后面可加数字,为before的意思,除了列出该行外,前面的n行也列出来;
  • –color=auto可将正确的那个选项数据列出颜色。

grep最重要的功能就是进行字符串数据的比对,然后将符合用户需求的字符串打印出来。

grep在数据中查寻出一个字符串时,是以【整行】为单位来进行数据的选取。

11.2.3 基础正则表达式练习-pg366

在文件中查找tast或test字样的字符串:

grep -n 't[ae]st' filename		

[]里面不论有几个字符,它都仅代表某【一个】字符。

行首^和行尾$:

那个^符号,在字符集合符号(括号[])之内与之外是不同的。在[]内代表反向选择。在[]之外则代表定位在行首的意义。

在正则表达式当中的【.】则代表【绝对有一个任意字符】的意思,这两个符号在正则表达式的意义如下:

  • .(小数点): 代表【一定由一个任意字符】的意思;
  • *(星星号): 代表【重复前一个字符,0到无穷多次】的意思,为组合形态。

想找出g后面接2到5个o,然后再接一个g的字符串:

grep -n 'go\{2,5\}g' filename		

11.2.4 基础正则表达式字符集合(characters)-pg371

RE字符意义与范例
^word意义:待查找的字符串(word)在行首
word$意义:待查找的字符串(word)在行尾
.意义:代表【一定有一个任意字符】的字符
\意义:转义符,将特殊符号的特殊意义去除
*意义:重复零个到无穷多个的前一个RE字符
[list]意义:字符集合的RE字符,里面列出想要选取的字符
[n1-n2]意义:字符集合的RE字符,里面列出想要选取的字符范围
[^list]意义:字符集合的RE字符,里面列出不要的字符串或范围
\{n,m\}意义:连续n到m个的【前一个RE字符】
意义:若为\{n\}则是连续n个的前一个RE字符
意义:若为\{n,\}则是连续n个以上的前一个RE字符

11.2.5 sed工具-pg373

sed本身也是一个管道命令,可以分析标准输入。而且sed还可以将数据进行替换、删除、新增、选取特定行等功能。

  • sed
sed [-nefr] [操作]

选项与参数:

  • -n : 使用安静(silent)模式,在一般sed的用法中,所有来自stdin的数据一般都会被列出到屏幕上。但如果加上-n参数后,则只有经过sed特殊处理的那一行(或操作)才会被列出来;
  • -e : 直接在命令行模式上进行sed的操作编辑;
  • -f : 直接将sed的操作写在一个文件内,-f filename则可以执行filename内的sed操作;
  • -r : sed的操作使用的是扩展型正则表达式的语法。(默认是基础正则表达式语法)
  • -i : 直接修改读取的文件内容,而不是由屏幕输出。

操作说明(如sed ‘2,5d’,操作得用’ '包裹起来使用):[n1[,n2]]function

  • n1,n2 : 不见得会存在,一般代表【选择进行操作的行数】,举例来说,如果我的操作是需要在10到20行之间进行的,则【10,20[操作行为]】;
  • function有下面这些东西:
    • a : 新增,a的后面可以接字符,而这些字符会在新的一行出现(目前的下一行);
    • c : 替换,c的后面可以接字符,这些字符可以替换n1,n2之间的行;
    • d : 删除,因为是删除,所以d后面通常不接任何东西;
    • i : 插入,i的后面可以接字符,而这些字符会在新的一行出现(目前的上一行);
    • p : 打印,亦即将某个选择的数据打印出来,通常p会与参数sed -n一起运行;
    • s : 替换,可以直接进行替换的工作,通常这个s的操作可以搭配正则表达式,例如1,20s/old/new/g就是。

11.3 扩展正则表达式-pg376

扩展正则表达式用grep -E或者是egrep(推荐)来表示。

RE字符意义与范例
+意义:重复【一个或一个以上】的前一个RE字符
?意义:【零个或一个】的前一个RE字符
|意义:用或(or)的方式找出数个字符串
( )意义:找出【群组】字符串
( )+意义:多个重复群组的判别

11.4 文件的格式化与相关处理

11.4.1 格式化打印:printf-pg377

  • printf
printf '打印格式' 实际内容

选项与参数:

关于格式方面有几个特殊的样式:

  • \a : 警告声音输出;
  • \b : 退格键(backspace);
  • \f : 清楚屏幕(form feed);
  • \n : 输出新的一行;
  • \r : 亦即回车按键;
  • \t : 水平的[tab]按键;
  • \v : 垂直的[tab]按键;
  • \xNN : NN为两位数的数字,可以转换数字成为字符。

关于c语言程序内,常见的变量格式:

  • %ns : 那个n是数字,s代表string,亦即多少个字符;
  • %ni : 那个n是数字,i代表integer,亦即多少整数位数;
  • %N.nf : 那个n与N是数字,f代表floating(浮点),如果有小数位数(比如8.2就是代表精度是00000.00)。

11.4.2 awk:好用的数据处理工具-pg379

awk是一个非常棒的数据处理工具,相较于sed常常作用于一整个行的处理,awk则比较倾向于一行当中分成数个字段来处理。因此,awk相当于适合处理小型的文本数据。

  • awk
awk '条件类型1{操作1} 条件类型1{操作1} ...' filename

awk可以处理后续接的文件,也可以读取来自前个命令的标准输出。

awk主要是处理每一行的字段内容的数据,而默认的字段的分隔符为"空格键"或"[Tab]键"。

具体例子看书pg379

取出第一列和第三列数据:

awk 'print $1 "\t" $3'

$0代表【一整列数据】

变量名称代表意义
NF每一行($0)拥有的字段总数
NR目前awk所处理的是第几行数据
FS目前的分割字符,默认是空格键
  • awk的逻辑运算字符
运算单元代表意义
>大于
<小于
>=大于或等于
<=小于或等于
==等于(基于判断)
!=不等于

几个重要的事项先说明:

  • awk的命令间隔:所有awk的操作,亦即再{}内的操作,如果有需要多个命令辅助时,可利用分号【;】间隔,或直接以[Enter]按键来隔开每个命令;
  • 逻辑运算当中,如果是【等于】的情况,则务必使用两个等号【==】;
  • 格式化输出时,在printf的格式设置当中,务必加上\n,才能进行分行。因为printf不能自动换行,print为内置语句,可以自动换行;
  • 与bash shell的变量不同,在awk当中,变量可以直接使用,不需加上$符号。

11.4.3 文件比对工具-pg381

  • diff

diff就是用在比对两个文件之间的差异,并且是以****为单位来比对,一般是用在ASCII纯文本文件的比对上。

diff通常是用在同一个文件(或软件)的新旧版本差异上。

diff [-bBi] from-file to-file

选项与参数:

- from-file : 一个文件名,作为原始比对文件的文件名;
- to-file : 一个文件名,作为目标比对文件的文件名;

注意,from-file或to-file可以用-替换,那个-代表【标准输入】之意。

- -b : 忽略一行当中,仅有多个空白的差异;
- -B : 忽略空白行的差异;
- -i : 忽略大小写的不同。
  • cmp

cmp主要也是比对两个文件,它主要利用**字节**为单位去比对,因此,当然也可以比对二进制文件。

cmp [-l] file1 file2

选项与参数:

- -l : 将所有不同点的字节处都列出来,因为cmp默认仅会输出第一个发现的不同点。
  • patch

patch这个命令与diff可是有密不可分的关系。先比较新旧版本的差异,并将差异文件制作成为补丁文件,再由补丁文件更新旧文件即可。

一般来说,使用diff制作出来的比较文件通常使用扩展名为.patch。

patch -pN < patch_file   	<==更新
patch -R -pN < patch_file	<==还原

选项与参数:

- -p : 后面可以接【取消几层目录】的意思;
- -R : 代表还原,将新的文件还原成原来旧的版本。

11.4.4 文件打印设置:pr-pg384

例子:想要打印 /etc/man_db.conf

pr /etc/man_db.conf

拾贰、第十二章-学习shell脚本(很重要)


12.1 什么是shell脚本

shell脚本(shell script,程序化脚本)是利用shell的功能写的一个【程序(program)】。这个程序是使用纯文本文件,将一些shell的语法与命令(含外部命令)写在里面。搭配正则表达式、管道命令与数据流重定向等功能,以达到我们所想要的处理目的。

12.1.1 为什么要学习shell脚本-pg388

  • 自动化管理的重要根据
  • 跟踪与管理系统的重要工作
  • 简单入侵检测功能
  • 连续命令单一化
    • 脚本最简单的功能就是:【集合一些在命令行的连续命令,将它写入脚本文件当中,而由直接执行脚本来启动一连串的命令行命令输入。】
  • 简易的数据处理
  • 跨平台支持与学习历程较短

shell脚本用在系统管理上面是很好的一项工具,但是用在处理大量数值运算上,就不够好了,原因在于shell脚本的速度较慢,且使用的CPU资源较多,会造成主机资源的分配不良。

12.1.2 第一个脚本的编写与执行-pg389

在shell脚本的编写中还需要注意下面的事项:

  1. 命令是自上而下、从左到右地分析与执行;
  2. 命令的执行就如同第4章内提到的:命令、选项与参数间的多个空格都会被忽略掉;
  3. 空白行也将被忽略掉,并且[Tab]按键所产生的空白同样视为空格键;
  4. 如果读取到一个Enter符号(CR),就尝试开始执行该行(该串)命令
  5. 至于如果一行的内容太多,则可以使用【[Enter]】来扩展至下一行;
  6. 【#】可做为注释,任何加在#后面的数据将全部被视为注释文件而被忽略。

执行shell文件,可以用如下方法:

  • 直接命令执行:shell.sh文件必须要具备可读与可执行(rx)的权限,然后:
  • 绝对路径:使用 /home/dmtsai/shell.sh 来执行命令;
  • 相对路径:假设工作目录在 /home/dmtsai,则使用 ./shell.sh 来执行;
  • 变量【PATH】功能:将shell.sh放在PATH指定的目录内,例如: ~/bin/;
  • 以bash程序来执行:通过【bash shell.sh】或【sh shell.sh】来执行。

编写第一个脚本:

(输入)mkdir bin;cd bin
bin==> 	vim hello.sh
(编辑脚本内容)
(#!/bin/bash)
#
#
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
exprot PATH
echo -e "Hello World! \a \n"
exit 0
  1. 第一行 #!/bin/bash 在声明这个脚本使用的shell名称;
  2. 程序内容的说明;
  3. 主要环境变量的声明(exprot PATH);
  4. 主要程序部分(echo);
  5. 执行结果告知(定义返回值,exit 0).

12.1.3 建立shell脚本的良好编写习惯-pg391

养成良好的脚本编写习惯,在每个脚本的文件头处记录好:

  • 脚本的功能;
  • 脚本的版本信息;
  • 脚本的作者与联络方式;
  • 脚本的版权声明方式;
  • 脚本的History(历史记录);
  • 脚本内较特殊的命令,使用【绝对路径】的方式来执行;
  • 脚本运行时需要的环境变量预先声明与设置。

包覆的内部程序代码最好能以[Tab]按键的空格向后推。

另外,编写脚本的工具最好使用vim而不是vi,因为vim会有额外的语法检验功能,能够在第一阶段编写时就发现语法方面的问题。


12.2 简单的shell脚本练习

自己练习

利用【$((计算式))】来进行数值运算

12.2.2 脚本的执行方式差异(source、sh script、 ./script)-pg394

  • 利用直接执行的方式来执行脚本:在子进程中进行

重点在于【当子进程完成后,在子进程内的各项变量或操作将会结束而不会传回到父进程中】。

  • 利用source来执行脚本:在父进程中进行

12.3 善用判断式

12.3.1 利用test命令的测试功能-pg395

测试的参数代表意义
1.关于某个文件名的【文件类型】判断,如test -e filename
-e该【文件名】是否存在(常用)
-f该【文件名】是否存在且为文件(file)(常用)
-d该【文件名】是否存在且为目录(dictionary)(常用)
-b该【文件名】是否存在且为一个 block device 设备
-c该【文件名】是否存在且为一个 character device 设备
-S该【文件名】是否存在且为一个socket文件
-p该【文件名】是否存在且为一个FIFO(pipe)文件
-L该【文件名】是否存在且为一个链接文件
2.关于文件的权限检测,如test -r filename
-r检测该文件名是否存在且具有【可读】的权限
-w检测该文件名是否存在且具有【可写】的权限
-x检测该文件名是否存在且具有【可执行】的权限
-u检测该文件名是否存在且具有【SUID】的属性
-g检测该文件名是否存在且具有【SGID】的属性
-k检测该文件名是否存在且具有【Sticky bit】的属性
-s检测该文件名是否存在且为【非空文件】
3.两个文件之间的比较,如test file1 -nt file2
-nt(newer than)判断file1是否比file2新
-ot(older than)判断file1是否比file2旧
-ef判断file1与file2是否为同一文件,可用在判断hard link的判定上。主要意义在判定,两个文件是否均指向同一个inode
4.关于两个整数之间的判定,如test n1 -eq n2
-eq两数值相等(equal)
-ne两数值不等(not equal)
-gtn1大于n2(greater than)
-ltn1小于n2(less than)
-gen1大于等于n2(greater than or equal)
-len1小于等于n2(less than or equal)
5.判定字符串的数据
test -z string判定字符串是否为0?若string为空字符串,则为true
test -n string判定字符串是否非为0?若string为空字符串,则为false。注:-n亦可忽略
test str1 == str2判定str1是否等于str2,若相等,则返回true
test str1 != str2判定str1是否不等于str2,若相等,则返回false
6.多重条件判定,例如:test -r filename -a -x filename
-a(and)两条件同时成立。例如tset -r file -a -x file,则file同时具有r与x权限时,才返回true
-o(or)两条件任何一个成立。例如tset -r file -o -x file,则file同时具有r与x权限时,就可返回true
!反相状态,如test ! -x file,当file不具有x时,返回true

由于root在很多权限的限制上面都是无效的,所以使用root执行这个脚本时,常常会发现与ls -l观察到的结果并不相同。

12.3.2 利用判断符号-pg397

还可以利用判断符号【[]】(就是中括号)来进行数据的判断。

注意:中括号两端需要有空格符来分割,比如: [ -z $() ]

  • 在中括号[]内的每个组件都需要有空格来分割;
  • 在中括号内的变量,最好都以双引号括号起来;
  • 在中括号内的常数,最好都以单或双引号括号起来。

12.3.3 shell脚本的默认变量-pg399

比如:

/path/to/scriptname opt1 opt2 opt3 opt4
(第一列是$0,第二列是$1,以此类推)
  • $# : 代表后接的参数【个数】,以上表为例这里显示为【4】;
  • $@ : 代表【“$1"”$2"“$3"”$4"】之意,每个变量是独立的(用双引号括起来);
  • $* : 代表【“$1c$2c$3c$4c”】,其中c为分割字符,默认为空格,所以本例中代表【“$1 $2 $3 $4”】之意。

注意:shift可以移动变量,而且shift后面可以接数字,代表拿掉前面几个参数的意思。


12.4 条件判断式

12.4.1 利用if…then-pg401

  • 单层、简单条件判断式
if [ 条件判断式 ];then
		当条件判断式成立时,可以进行的命令工作内容;
fi		<==将if反过来写,就成为fi,结束if的意思。
- && 代表AND
- || 代表OR
  • 多重、复杂条件判断式
#一个条件判断,分成功执行与失败执行(else)
if [ 条件判断式 ];then
		当条件判断式成立时,可以进行的命令工作内容;
else
		当条件判断式不成立时,可以进行的命令工作内容;
fi		<==将if反过来写,就成为fi,结束if的意思。

如果考虑更复杂的情况:

#多个条件判断,分多种不同情况执行(if...elif...elif...else)
if [ 条件判断式一 ];then
		当条件判断式一成立时,可以进行的命令工作内容;
elif [ 条件判断式二 ];then
		当条件判断式二成立时,可以进行的命令工作内容;
else
		当条件判断式一与二均不成立时,可以进行的命令工作内容;
fi		<==将if反过来写,就成为fi,结束if的意思。

学一个有趣的命令

  • netstat

这个命令可以查询到目前主机开启的网络服务端口(service ports),利用【netstat -tuln】来获取目前主机启动的服务。

几个常见的端口与相关网络服务的关系:

  • 80 : WWW
  • 22 : ssh
  • 21 : ftp
  • 25 : mail
  • 111 : RPC(远程过程调用)
  • 631 : CUPS(打印服务功能)

12.4.2 利用case…esac-pg405

case $变量名称 in		<==关键字是case,还有变量前有美元符号。
	"第一个变量内容")		<==每个变量内容建议用双引号括起来,关键字则为右圆括号。
		程序段
		;;				<==每个内别结尾使用两个连续的分号来处理。
	"第二个变量内容")		<==每个变量内容建议用双引号括起来,关键字则为右圆括号。
		程序段
		;;				<==每个内别结尾使用两个连续的分号来处理。
	*)					<==最后一个变量内容都会用*来代表所有其他值。
		不包含第一个变量内容与第二个变量内容的其他程序执行段。
		exit 1
		;;
esac					<==将case反过来写,就成为esac,结束case的意思。

一般来说,使用【case 变 量 i n 】 这 个 语 法 时 , 当 中 的 那 个 【 变量 in】这个语法时,当中的那个【 in变量】大致有两种获取方法:

  • 直接执行式:例如上面提到的,利用【 script.sh variable 】的方式来直接给予 $1 这个变量的内容,这也是在 /etc/init.d 目录下大多数程序的设计方式;
  • 交互式:通过read这个命令来让用户输入变量的内容。

12.4.3 利用利用function功能-pg406

function fname(){
	程序段
}

注意:因为shell脚本的执行方式是从上到下、从左到右,因此在shell脚本当中的function的设置一定要在程序的最前面。

function也是拥有内置变量的,它的内置变量与shell脚本很类似,函数名称代表示 $0 ,后续接的变量也是以 $1、$2…来替换的。


12.5 循环(loop)

12.5.1 while do done、until do done(不定循环)-pg408

while [ condition ]		<==中括号内的状态就是判断式
do						<==do是循环的开始
	程序段落
done					<==done是循环的结束

while是【当condition条件成立时,就进行循环,直到condition的条件不成立才停止】

until [ condition ]		<==中括号内的状态就是判断式
do						<==do是循环的开始
	程序段落
done					<==done是循环的结束

until与while相反,它是【当condition条件成立时,就终止循环,否则就持续进行循环的程序段】

12.5.2 for…do…done(固定循环)-pg409

for这种语法,则是【已经知道要进行几次循环】的状态

for var in con1 con2 con3 ...
do
	程序段
done

这个 $var 的变量内容在循环工作时:

  1. 第一次循环时,$var的内容为con1;
  2. 第二次循环时,$var的内容为con2;
  3. 第三次循环时,$var的内容为con3;
$(seq 1 100)	# seq为sequence(连续)的缩写之意

还可以使用 {1…100}来替换$(seq 1 100),都是从1到100连续取值的含义。

12.5.3 for…do…done的数值处理-pg411

for (( 初始值;限制值;赋值运算 ))
do
	程序段
done

for括号内的含义:

  • 初始值 : 某个变量在循环当中的起始值,直接以类似i=1设置好;
  • 限制值 : 当变量的值在这个限制值的范围内,就继续进行循环,例如i<=100;
  • 赋值运算 : 每做一次循环,变量也变化,例如i=i+1。

12.6 shell脚本的跟踪与调试-pg413

sh [-nvx] scripts.sh

选项与参数:

  • -n : 不要执行脚本,仅查询语法的问题;
  • -v : 再执行脚本前,先将脚本文件的内容输出到屏幕上;
  • -x : 将使用到的脚本内容显示到屏幕上,这是很有用的参数。

在输出信息中,在加号后面的数据其实都是命令串,由于sh -x的方式将命令执行过程也显示出来,这样用户就可以判断程序代码执行到哪一段时会出现相关的信息。


第四部分 Linux使用者管理


拾叁、第十三章-Linux账户管理与ACL权限设置


13.1 Linux的账号与用户组

13.1.1 用户标识符:UID与GID-pg418

  • 用户ID(User ID,简称UID)
  • 用户组ID(Group ID,简称GID)

13.1.2 用户账号-pg419

输入账号密码后,系统帮你处理了什么呢?

  1. 先查找 /etc/passwd 里面是否有你输入的账号?如果没有则退出,如果有的话则将该账号对应的UID与GID(在 /etc/group 中)读出来,另外,该账号的家目录与shell设置也一并读出来;
  2. 再来则是核对密码表。这时Linux会进入 /etc/shadow 里面找出对应的账号与UID,然后核对一下你刚刚输入的密码与里面的密码是否相符?
  3. 如果一切都OK的话,就进入shell管理的阶段。

介绍两个结构:

  • /etc/passwd文件结构

每一行都代表一个账号,有几行就代表有几个账号在你的系统中。不过需要特别留意的是,里面很多账号本来就是系统正常运行所必须的,我们可以简称它为系统账号。

root:x:0:0:root:/root:/bin/bash

每一行都用【:】分格,一共七项,分别代表:

  • 账号名称
  • 密码
    • 以前的密码存放于此,现在将这个字段的密码数据改放到 /etc/shadow 中了,所以会看到一个【x】。
  • UID
ID范围该ID用户特性
0(系统管理员)当UID是0时,代表这个账号是【系统管理员】,所以当你要让其他的账号名称也具有root的权限时,将该账号的UID改为0即可。
1~999(系统账号)保留给系统使用的ID。
根据系统账号的由来,通常这类账号又大概被区分为两种:
- 1-200:由Linux发行版自行建立的系统账号;
- 201-999:若用户有系统账号需求时,可以使用的账号UID
1000~60000(可登录账号)给一般用户使用。
- GID - 这个与 /etc/group 有关,其实 /etc/group 的概念和 /etc/passwd 差不多,只是它用来规范组名与GID的对应而已。 - 用户信息说明栏 - 用来解释账号的意义。不过如果使用finger的功能时,这个字段可以提供很多的信息。 - 家目录 - 这是用户的家目录。 - shell - 当用户登录系统以后,就会获取一个shell来与系统的内核沟通以进行用户的操作任务。

第二个结构:

  • /etc/shadow文件结构

同样的,shadow每一行也都用【:】分格,一共九项,分别代表:

  1. 账号名称
    • 必须和 /etc/passwd 相同。
  2. 密码
    • 这个字段内的数据才是真正的密码,而且是经过编码的密码。只有root才可以读写;
    • 当你修改这个字段后,该密码就会失效(算不出来)。很多软件通过这个功能,在此字段前加上!或*修改密码字段,就会让密码【暂时失效】。
  3. 最近修改密码的日期
    • 注意:Linux日期的时间是以1970年1月1日作为1而累加的日期。
  4. 密码不可被修改的天数(与第三字段相比)
    • 如果是0则表示密码可以随时修改。
  5. 密码需要重新修改的天数(与第三字段相比)
    • 经常修改密码是一个好习惯。你必须要在这个天数内重新设置你的密码,否则这个账号的密码就会【变为过期特性】。
  6. 密码需要修改期限前的警告天数(与第五字段相比)
    -当密码快过期时,系统会发出【警告】信息提醒这个账号。
  7. 密码过期后的账号宽限时间(密码失效日)(与第五字段相比)
    • 密码有效日期为【更新日期(第三字段)】+【重新修改日期(第五字段)】,过了该期限后用户依旧没有更新密码,那改密码就算过期了;
    • 不过如果密码过期了,那当你登录系统时,系统会强制要求你必须要重新设置密码才能登录继续使用,这就是密码过期特性。
  8. 账号失效日期
    • 表示这个账号在此字段规定的日期之后,将无法再使用。这就是所谓的【账号失效】,此时无论你的密码是否过期,这个【账号】都不能再被使用。
  9. 保留
    • 最后一个字段是保留的,看以后有没有新功能加入。

如果我忘记密码了,应该怎么办?

  • 一般用户的密码忘记了:这个最容易解决,请系统管理员帮忙,它会重新设置好你的密码而不需要知道你的旧密码,以root的身份使用passwd命令来处理即可;
  • root密码忘记了:这就麻烦了,因为你无法使用root的身份登录了。但我们知道root的密码在 /etc/shadow 当中,因此你可以使用各种可行的方法启动进入Linux再去修改。

13.1.3 关于用户组:有效与初始用户组,groups,newgr-pg423

  • /etc/group 文件结构

这个文件就是记录GID与组名的对应记录,每一行代表一个用户组,也是以【:】作为字段的分隔符,共分为四栏,分别代表:

  1. 组名
    • 需要与第三字段的GID对应。
  2. 用户组密码
    • 同样移到 /etc/passwd中。
  3. GID
    • 用户组ID。
  4. 此用户组支持的账号名称
    • 一个账号可以加入多个用户组,如果某个账号想要加入此用户组时,将该账号填入这个字段即可。

关于有效任务组(effective group)与初始用户组(initial group)。GID就是初始用户组。

  • group:有效与支持用户组的观察
group
==> dmtsai wheel users

输出三个用户组,第一个输出的用户组即为有效用户组(effective group)。

  • newgrp:有效用户组的切换
newgrp
group
==> users wheel dmtsai

使用newgrp是有限制的,那就是你想要切换的用户组必须是你已经有支持的用户组。

  • /etc/gshadow

这个文件内同样还是使用【:】来作为字段的分割字符,几乎与 /etc/group 一模一样。要注意的就是第二个字段,第二字段为密码栏,如果密码栏上面是【!】或为空时,表示该用户组不具有用户组管理员。

这四个字段意义是:

  1. 组名;
  2. 密码栏,同样的,开头为【!】或为空时,表示该用户组不具有用户组管理员;
  3. 用户组管理员的账号(相关信息在gpasswd中介绍);
  4. 有加入该用户组支持的所属账号(与 /etc/group 内容相同)。

13.2 账号管理

13.2.1 新增与删除用户:useradd、相关配置文件、passwd、usermod、userdel-pg418

  • useradd
useradd [-u UID] [-g 初始用户组] [-G 次要用户组] [-mM]\
> [-c 说明栏] [-d 家目录绝对路径] [-s shell] 使用者账号名

注意: \ > 代表换行符。

选项与参数:

  • -u : 后面接的是UID,是一组数字,直接指定一个特定的UID给这个账号;
  • -g : 后面接的用户组就是上面提到的初始用户组。该用户组的GID会被放到 /etc/passwd 的第四栏位内;
  • -G : 后面接的用户组则是该账号还可以加入的用户组,这个选项与参数会修改 /etc/group 内的相关内容;
  • -M : 强制,不要建立使用者家目录。(系统账号默认值);
  • -m : 强制,要建立使用者家目录。(一般账号默认值);
  • -c : 这个就是 /etc/passwd 的第五栏的说明内容,可以随便我们设置的;
  • -d : 指定某个目录成为家目录,而不要使用默认值,务必使用绝对路径;
  • -r : 建立了一个系统的账号,这个账号的UID会有限制;
  • -s : 后面接一个shell,若没有指定则默认是 /bin/bash;
  • -e : 后面接一个日期,格式为【YYYY-MM-DD】此选项可写入shadow第八栏位,亦即账号失效日的设置选项;
  • -f : 后面接shadow的第七栏位选项,指定密码是否会失效,0为立刻失效;
  • -l : 为永远不失效(密码只会过期而强制于登陆时重新设置而已)。

CentOS这些默认值主要会帮我们处理几个选项:

  • 在 /etc/passwd 里面建立一行与账号相关的数据,包括建立 UID/GID/家目录等;

  • 在 /etc/shadow 里面将此账号的密码相关参数写入,但是尚未有密码;

  • 在 /etc/group 里面加入一个与账号名称一模一样的组名;

  • 在 /home 下面建立一个与账号同名的目录作为用户家目录,且权限为700。

  • useradd参考文件

useradd -D

查看数据,这些数据其实是由 /etc/default/useradd 调用出来的。

  • GROUP=100:新建账号的初始用户组使用GID为100;
    • 私有用户组机制
      • 系统会建立一个与账号一样的用户组用户作为初始用户组;
    • 公共用户组机制
      • 就是以GROUP=100这个设置值作为新建账号的初始用户组,因此每个账号都属于users这个用户组,且权限都一致。
  • HOME=/home:用户家目录的基准目录(basedir)
  • INACTIVE = 1:密码过期后是否会失效的设置值;
    • 0表示密码过期立刻失效,-1表示永远不会失效。
  • EXPIRE=:账号失效的日期;
  • SHELL=/bin/bash:默认使用的shell程序文件名;
  • SKEL=/etc/skel:用户家目录参考基准目录
  • CREATE MAIL_SPOOL=yes:建立用户的mailbox;

UID/GID的密码参数在 /etc/login.defs 里面,文件的内容如下:

  • mailbox所在目录;
    • 用户默认mailbox文件放置目录是 /var/spool/mail;
  • shadow密码第4、5、6字段内容;
    • 通过PASS_MAX_DAYS等设置值来指定;
  • UID/GID指定数值;
  • 用户家目录设置值;
  • 用户删除与密码设置值;
    • 使用【USERGROUPS_ENAB_yes】这个设定值的功能是:如果使用userdel去删除一个账号,且该账号所属的初始用户组已经没有人隶属于该用户组了,那么就删除掉该用户组。

接下来处理用户密码。

  • passwd
passwd [--stdin] [账号名称] 			<==所有人均可使用来改自己的密码
passed [-l] [-u] [--stdin] [-S] [-n 日期] [-x 日期] [-w 日期] [-i 日期] 账号
<==上面这个是root功能

选项与参数:

  • –stdin : 可以通过来自前一个管道的数据,作为密码输入,对shell脚本有帮助;

点击跳转

更多推荐

鸟哥的Linux私房菜(基础学习篇第四版)学习笔记