Linux-00-大全手册

Linux-00-大全手册

开篇词

1. 常用命令部分

1.1 文件查看

1. ls 命令

mark

注意

  1. 隐藏文件是以`开头
  2. 第一列权限符代表的是文件的类型
    • 例如 d 代表的是文件夹
    • 例如 - 代表的就是普通文件
  3. ls -R 会递归显示当前所有文件夹下面的文件

mark

2. cd 命令

mark

注意 :

  1. 执行man cd不会显示cd 的工作帮助,会显示bash 的帮助
    • cd 是 bash 的内置命令
    • 获取内置命令帮助 需要 help cd
mark

mark

  1. 小技巧
    1. cd - 会回到上一次所在的目录
    2. cd ../ 返回当前目录的上一级目录
    3. cd .. 返回当前目录的上一级目录
    4. cd ./下一级目录名 :进入下一级目录

1.2 文件操作

1. mkdir 命令

  1. mkdir -p /a/b/c/d
    • 在 根目录下 创建 多级目录 /a/b/c/d

mark

2. rm 命令

  1. 删除空目录 – rmdir
  2. 删除非空目录 – rm -r

mark

注意 :

  1. rm -rf 不会显示提示 删除对应文件夹下的所有非空文件和目录
  2. rm -r 会有提示的删除对应文件下所有非空的文件和目录

mark

3. cp 命令

  • 复制文件(copy

mark

注意

  1. cp 是用来普通复制文件的,如果想要复制目录 需要加上参数 cp -r
  2. cp -p 会保留复制文件的属性参数(时间 权限。。。。)

4. mv 命令

  1. 重命名 文件 : mv filename1 filename2
  2. 移动文件mv sourcepath/sourfile destpath
  3. 移动并且重命名文件mv sourcepath/sourfile destpath/destfile

mark

5. 通配符

  1. * 匹配多个字符
  2. ? 匹配单个字符
  3. 以上两个符号可以和命令结合使用

mark

1.3 文本查看

mark

1. cat

2. head

  • 默认查看前十行的信息

3. tail

  • 默认查看后十行的信息

  • tail -f 同步进行更新尾部的信息 (适用于tomcat日志文件)

4. wc

  • wc -l 查看文件有多少行 再决定是否用cat选项

5 more

  • 分页显示前面内容
  • 使用空格继续显示后续内容

6. less

  • less 与 more 类似,但使用 less 可以随意浏览文件,而 more 仅能向前移动,却不能向后移动,而且 less 在查看之前不会加载整个文件。
1
less [参数] 文件

1.4 文件打包和压缩

1. 打包和压缩

注意:

  1. 打包和压缩对于Linux来说 是分开的步骤

mark

例如 : tar cf /tmp/etc-backup.tar /etc

  • c 打包命令
  • f 打包成文件
  • /tmp/etc-backup.tar /打包到哪里去/打包的文件名叫什么
  • /etc 对哪个目录进行打包

mark

例如 : tar czf /tmp/etc-backup.tar /etc

  • c 打包命令
  • f 打包成文件
  • 打包选项
    • j 是使用bz2 进行压缩 tar cjf /tmp/etc-backup.tar.bz2 /etc
    • z 是使用gzip 进行压缩 tar czf /tmp/etc-backup.tar.gz /etc
  • /tmp/etc-backup.tar /打包到哪里去/打包的文件名叫什么
  • /etc 对哪个目录进行打包

mark

注意 :

  • bz2 压缩的时间会比 gzip 的时间长
  • bz2 压缩的文件大小会比gzip 的文件小

mark

2. 解压缩

mark

例如 : tar xf /tmp/etc-backup.tar -C /root

  • x 解包
  • f 解包为文件
  • /tmp/etc-backup.tar 对谁进行解包
  • -C 放在什么位置需要加上
  • /root 解压完放在哪个目录下
  • 解包选项
    • j 是使用bz2 进行压缩 tar xjf /tmp/etc-backup.tar.bz2 /root
    • z 是使用gzip 进行压缩 tar xzf /tmp/etc-backup.tar.gz /root

注意 :双扩展名缩写

  • .tar.bz2 = .tbz2
  • .tar.gz = .tgz

2. 文本编辑器 vi

  1. 输入 vim 或 vi

mark

  1. vim 的四种工作模式

mark

  • Vim是从 vi 发展出来的一个文本编辑器。代码补完、编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用。
  • 简单的来说, vi 是老式的字处理器,不过功能已经很齐全了,但是还是有可以进步的地方。 vim 则可以说是程序开发者的一项很好用的工具。
  • vim 官网https://www.vim.org/
  • 菜鸟教程https://www.runoob.com/linux/linux-vim.html

mark

mark

2.1 vim 正常模式

  1. 插入模式
    • i 进入插入模式
    • I 进入插入模式 : 光标来到本行的开头
    • a 进入插入模式: 光标来到插入位置的后一位
    • A进入插入模式: 光标来到本行的末尾
    • o 进入插入模式 : 光标来到当前的下一行,并在下方产生一个新的空行
    • O 进入插入模式 : 光标来到当前的上一行,并在上方产生一个新的空行
  1. 复制剪切粘贴
    • yy : 进行整行的复制
      • 3yy 连续复制三行数据
    • y$ : 复制从光标的位置到本行结尾的数据
    • p : 进行整行的粘贴
    • dd : 剪切一整行
    • d$ : 剪切从光标到本行结尾
  1. 撤销和回撤
    • u : 普通模式下按u进行撤销/ 多次u多次撤销
    • ctrl + R : 撤销指令进行回撤(重新执行)
  1. 单个字符删除 / 替换
    • x : 删除光标指定的字符
    • r : 替换光标指定的字符
  1. 移动光标

    • g : 直接来到第一行第一个字符

    • G : 直接来到最后一行第一个字符

    • 数字 + G : 直接移动到对应数字指定的行

    • h : 光标向左移动

    • j : 光标向下移动

    • k : 光标向上移动

    • l : 光标向右移动

    • shift + 6 = ^ : 来到这一行的开头

    • shift + 4 = $ 来到这一行的结尾

    • 数字 + 空格 : 光标移动到数字个字符后的位置

    • 数字 + 回车 : 光标移动到n行以后的位置

2.2 vim 命令行模式

  1. 保存 / 退出
    • : : 光标来到最后一行
    • :w /root/a.txt : 保存 到 root 下面 ,文件名 a.txt
    • :q : 退出
    • :wq : 保存并且退出
    • :q! : 不保存并且退出
  1. 同时执行linux命令
    • :! + 命令 : 在vim模式下执行linux命令
  1. 查找命令/替换
    • / + 要查找的内容
      • 查找到之后 使用 n 来查找下一个匹配的位置
      • 查找到之后 使用 N 来查找上一个匹配的位置
    • :s/old/new : 查找到旧的(old) 替换成新的字符(new)
      • 本操作默认只针对光标所在的这一行
      • :%s/old/new : 全文new替换单一个位置的old
      • :%s/old/new/g : 全文new 替换所有位置的old (g = global)
      • :3,5s/old/new/g 指定行new 替换所有位置的old (g = global)
  1. 修改配置
    • :set nu : 显示文本的行号 (暂时配置)
    • :set nonu : 不显示文本的行号(暂时配置)
    • vim /etc/vimrc : 进入配置文件进行配置 (永久配置)
      • 如 新建一行 set nu 永久显示行号

2.3 vim 可视模式

mark

  1. v :字符可视模式
  2. V : 行可视模式
  3. ctrl + v :块可视模式
    • 指定选中块 I添加元素
    • 指定选中块 d删除元素

3. 用户和用户组管理

手册链接 : [用户和用户组管理][https://www.runoob.com/linux/linux-user-manage.html]

  • Linux系统是一个多用户多任务的分时操作系统,任何一个要使用系统资源的用户,都必须首先向系统管理员申请一个账号,然后以这个账号的身份进入系统。
  • 用户的账号一方面可以帮助系统管理员对使用系统的用户进行跟踪,并控制他们对系统资源的访问;另一方面也可以帮助用户组织文件,并为用户提供安全性保护。

每个用户账号都拥有一个唯一的用户名和各自的口令。

用户在登录时键入正确的用户名和口令后,就能够进入系统和自己的主目录。

实现用户账号的管理,要完成的工作主要有如下几个方面:

  • 用户账号的添加、删除与修改。
  • 用户口令的管理。
  • 用户组的管理。

3.1 用户管理常用命令

mark

1. useradd

mark

1
useradd 选项 用户名

参数说明:

  • 选项:

    • -c comment指定一段注释性描述。
    • -d目录 指定用户主目录,如果此目录不存在,则同时使用-m选项,可以创建主目录。
    • -g 用户组 指定用户所属的用户组。
    • -G 用户组,用户组 指定用户所属的附加组。
    • -sShell文件 指定用户的登录Shell。
    • -u 用户号 指定用户的用户号,如果同时有-o选项,则可以重复使用其他用户的标识号。
  • 用户名:

    指定新账号的登录名。

注意

  • 两者对应的目录不同
    • root 默认在 /root
    • zhuuu 默认在 /home/同名目录
    • 同时操作系统会记录当前用户信息到配置文件中

mark

mark

2. passwd

  • 用户管理的一项重要内容是用户口令的管理。用户账号刚创建时没有口令,但是被系统锁定,无法使用,必须为其指定口令后才可以使用,即使是指定空口令。
  • 指定和修改用户口令的Shell命令是passwd超级用户可以为自己和其他用户指定口令,普通用户只能用它修改自己的口令。命令的格式为:
1
passwd 选项 用户名

mark

  • 例如,假设当前用户是sam,则下面的命令修改该用户自己的口令
1
2
3
4
$ passwd 
Old password:******
New password:*******
Re-enter new password:*******
  • 如果是超级用户,可以用下列形式指定任何用户的口令:
1
2
3
# passwd sam 
New password:*******
Re-enter new password:*******

3. userdel

  • 如果一个用户的账号不再使用,可以从系统中删除。
  • 删除用户账号就是要将etc/passwd等系统文件中的该用户记录删除,必要时还删除用户的主目录。
  1. 删除一个已有的用户账号使用userdel命令,其格式如下:
1
userdel 选项 用户名
  1. 常用的选项是 -r,它的作用是把用户的主目录一起删除。

    例如:

    1
    # userdel -r sam
  1. 此命令删除用户sam在系统文件中(主要是/etc/passwd, /etc/shadow, /etc/group等)的记录,同时删除用户的主目录。

mark

4. usermod

  • 修改用户账号就是根据实际情况更改用户的有关属性,如用户号、主目录、用户组、登录Shell等。

  • 修改已有用户的信息使用usermod命令,其格式如下:

1
usermod 选项 用户名
  • 常用的选项包括-c, -d, -m, -g, -G, -s, -u以及-o等,这些选项的意义与useradd命令中的选项一样,可以为用户指定新的资源值。

例如:

1
# usermod -s /bin/ksh -d /home/z –g developer sam

此命令将用户sam的登录Shell修改为ksh,主目录改为/home/z,用户组改为developer。

5. chage

  • 设置用户的生命周期

3.2 用户组管理

  • 每个用户都有一个用户组,系统可以对一个用户组中的所有用户进行集中管理。
  • 不同Linux 系统对用户组的规定有所不同,如Linux下的用户属于与它同名的用户组,这个用户组在创建用户时同时创建。

1. groupadd

  1. 方式一 : 新建用户组并且放入新用户

mark

  1. *方式二 : 新建用户组并且放入新用户 *

    mark

2. groupdel

1
groupdel 用户组

例如:

1
# groupdel group1

此命令从系统中删除组group1。

3.3 切换用户

mark

  1. su 切换用户
    • su - user1 : 表示工作环境同时切换为user1

mark

注意 :

  • 普通用户之间切换需要使用密码
  • root 用户切换不需要使用密码
  1. 授权普通用户进行关机命令
  • mark

  • root 用户设置30分钟后关机

  • user 用户取消30分钟后关机

  • mark

注意 : 在不告知user 密码的情况的下 : 使用shutdown -c 命令

  1. 给user 用户设置密码
  2. 使用visudo 命令
    • 在本配置文件下,可以给用户赋予不同权限
    • :!which shutdown 可以查找对应命令的目录在哪里
    • user3 ALL=/sbin/shutdown -c 加入对应的权限命令

mark

  1. 这时使用shutdown -c仍然会提示权限不够
    • 需要使用sudo /sbin/shutdown -c 并且输入用户密码才能取消

3.4 用户组的配置文件

  • 完成用户管理的工作有许多种方法,但是每一种方法实际上都是对有关的系统文件进行修改。

  • 与用户和用户组相关的信息都存放在一些系统文件中,这些文件包括/etc/passwd, /etc/shadow, /etc/group等。

下面分别介绍这些文件的内容。

1. /etc/passwd

  • /etc/passwd文件是用户管理工作涉及的最重要的一个文件。

  • Linux系统中的每个用户都在/etc/passwd文件中有一个对应的记录行,它记录了这个用户的一些基本属性。

  • 这个文件对所有用户都是可读的。它的内容类似下面的例子:

mark

  • 从上面的例子我们可以看到,/etc/passwd中一行记录对应着一个用户,每行记录又被冒号(:)分隔为7个字段,其格式和具体含义如下:
1
用户名:口令:用户标识号:组标识号:注释性描述:主目录:登录Shell
  1. 用户名
  • 通常长度不超过8个字符,并且由大小写字母和/或数字组成。登录名中不能有冒号(:),因为冒号在这里是分隔符。

    为了兼容起见,登录名中最好不要包含点字符(.),并且不使用连字符(-)和加号(+)打头。

  1. 口令
  • 虽然这个字段存放的只是用户口令的加密串,不是明文,
  • 但是由于/etc/passwd文件对所有用户都可读,所以这仍是一个安全隐患。
  • 因此,现在许多Linux 系统(如SVR4)都使用了shadow技术,把真正的加密后的用户口令字存放到/etc/shadow文件中,而在/etc/passwd文件的口令字段中只存放一个特殊的字符,例如“x”或者“*”。
  1. 用户id
  • 是一个整数,系统内部用它来标识用户。

  • 一般情况下它与用户名是一一对应的。如果几个用户名对应的用户标识号是一样的,系统内部将把它们视为同一个用户

  • 但是它们可以有不同的口令、不同的主目录以及不同的登录Shell等。

  • 通常用户标识号的取值范围是0~65 535。

    • 0是超级用户root的标识号,1~99由系统保留,作为管理账号
    • 普通用户的标识号从100开始。在Linux系统中,这个界限是500。
  1. 组id
  • 它对应着/etc/group文件中的一条记录。
  1. 注释性描述
  • 例如用户的真实姓名、电话、地址等,这个字段并没有什么实际的用途。在不同的Linux 系统中,这个字段的格式并没有统一。在许多Linux系统中,这个字段存放的是一段任意的注释性描述文字,用做finger命令的输出。
  1. 用户的工作目录
  • 它是用户在登录到系统之后所处的目录。在大多数系统中,各用户的主目录都被组织在同一个特定的目录下,而用户主目录的名称就是该用户的登录名。
  • 各用户对自己的主目录有读、写、执行(搜索)权限,其他用户对此目录的访问权限则根据具体情况设置。
  1. 用户使用的shell
  • 用户登录后,要启动一个进程,负责将用户的操作传递给内核,这个进程是用户登录到系统后运行的命令解释器或者某个特定的程序(shell
  • Shell是用户与Linux系统之间的接口。Linux的Shell有许多种,每种都有不同的特点。
    • 常用的有sh(Bourne Shell), csh(C Shell), ksh(Korn Shell), tcsh(TENEX/TOPS-20 type C Shell), bash(Bourne Again Shell)等。
    • 系统管理员可以根据系统情况和用户习惯为用户指定某个Shell。如果不指定Shell,那么系统使用sh为默认的登录Shell,即这个字段的值为/bin/sh。
    • 利用这一特点,我们可以限制用户只能运行指定的应用程序,在该应用程序运行结束后,用户就自动退出了系统
    • 有些Linux 系统要求只有那些在系统中登记了的程序才能出现在这个字段中。
  1. 伪用户
  • 这些用户在/etc/passwd文件中也占有一条记录,但是不能登录,因为它们的登录Shell为空
  • 它们的存在主要是方便系统管理,满足相应的系统进程对文件属主的要求。

常见的伪用户如下所示:

1
2
3
4
5
6
7
伪 用 户 含 义 
bin 拥有可执行的用户命令文件
sys 拥有系统文件
adm 拥有帐户文件
uucp UUCP使用
lp lp或lpd子系统使用
nobody NFS使用

注意:

  • /etc/passwd 中新增加一行 相当于手动的创建了一个新用户 `useradd`

2. /etc/shadow

  • 由于/etc/passwd文件是所有用户都可读的,如果用户的密码太简单或规律比较明显的话,一台普通的计算机就能够很容易地将它破解,因此对安全性要求较高的Linux系统都把加密后的口令字分离出来,单独存放在一个文件中,这个文件是/etc/shadow文件。 有超级用户才拥有该文件读权限,这就保证了用户密码的安全性。

  • /etc/shadow中的记录行与/etc/passwd中的一一对应,它由pwconv命令根据/etc/passwd中的数据自动产生

  • 下面是/etc/shadow的一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# cat /etc/shadow

root:Dnakfw28zf38w:8764:0:168:7:::
daemon:*::0:0::::
bin:*::0:0::::
sys:*::0:0::::
adm:*::0:0::::
uucp:*::0:0::::
nuucp:*::0:0::::
auth:*::0:0::::
cron:*::0:0::::
listen:*::0:0::::
lp:*::0:0::::
sam:EkdiSECLWPdSa:9740:0:0::::

它的文件格式与/etc/passwd类似,由若干个字段组成,字段之间用”:”隔开。这些字段是:

1
登录名:加密口令:最后一次修改时间:最小时间间隔:最大时间间隔:警告时间:不活动时间:失效时间:标志
  1. “登录名”是与/etc/passwd文件中的登录名相一致的用户账号
  2. “口令”字段存放的是加密后的用户口令字,长度为13个字符。如果为空,则对应用户没有口令,登录时不需要口令;如果含有不属于集合 { ./0-9A-Za-z }中的字符,则对应的用户不能登录。
  3. “最后一次修改时间”表示的是从某个时刻起,到用户最后一次修改口令时的天数。时间起点对不同的系统可能不一样。例如在SCO Linux 中,这个时间起点是1970年1月1日。
  4. “最小时间间隔”指的是两次修改口令之间所需的最小天数。
  5. “最大时间间隔”指的是口令保持有效的最大天数。
  6. “警告时间”字段表示的是从系统开始警告用户到用户密码正式失效之间的天数。
  7. “不活动时间”表示的是用户没有登录活动但账号仍能保持有效的最大天数。
  8. “失效时间”字段给出的是一个绝对的天数,如果使用了这个字段,那么就给出相应账号的生存期。期满后,该账号就不再是一个合法的账号,也就不能再用来登录了。

注意 :

  • 即使两个用户设置了相同的密码,在配置文件/etc/shadow 中保存的密码显示也是不一样的

4. /etc/group

  • 将用户分组是Linux 系统中对用户进行管理及控制访问权限的一种手段。
  • 每个用户都属于某个用户组;一个组中可以有多个用户,一个用户也可以属于不同的组。(多对多)
    • 当一个用户同时是多个组中的成员时,在/etc/passwd文件中记录的是用户所属的主组,也就是登录时所属的默认组,而其他组称为附加组。
    • 用户要访问属于附加组的文件时,必须首先使用newgrp命令使自己成为所要访问的组中的成员。
  • 用户组的所有信息都存放在/etc/group文件中。此文件的格式也类似于/etc/passwd文件,由冒号(:)隔开若干个字段,这些字段有:
1
组名:口令:组标识号:组内用户列表
  1. “组名”是用户组的名称,由字母或数字构成。与/etc/passwd中的登录名一样,组名不应重复。
  2. “口令”字段存放的是用户组加密后的口令字。一般Linux 系统的用户组都没有口令,即这个字段一般为空,或者是*。
  3. “组标识号”与用户标识号类似,也是一个整数,被系统内部用来标识组。(gid)
  4. “组内用户列表”是属于这个组的所有用户的列表,不同用户之间用逗号(,)分隔。这个用户组可能是用户的主组,也可能是附加组。

/etc/group文件的一个例子如下:

1
2
3
4
5
6
7
root::0:root
bin::2:root,bin
sys::3:root,uucp
adm::4:root,adm
daemon::5:root,daemon
lp::7:root,lp
users::20:root,sam

3.5 批量添加用户

  • 添加和删除用户对每位Linux系统管理员都是轻而易举的事,比较棘手的是如果要添加几十个、上百个甚至上千个用户时,我们不太可能还使用useradd一个一个地添加,必然要找一种简便的创建大量用户的方法。

  • Linux系统提供了创建大量用户的工具,可以让您立即创建大量用户,方法如下:

  1. 先编辑一个文本用户文件
  • 每一列按照/etc/passwd密码文件的格式书写,要注意每个用户的用户名、UID、宿主目录都不可以相同
  • 其中密码栏可以留做空白或输入x号。一个范例文件user.txt内容如下:
1
2
3
4
5
6
user001::600:100:user:/home/user001:/bin/bash
user002::601:100:user:/home/user002:/bin/bash
user003::602:100:user:/home/user003:/bin/bash
user004::603:100:user:/home/user004:/bin/bash
user005::604:100:user:/home/user005:/bin/bash
user006::605:100:user:/home/user006:/bin/bash
  1. 以root 的身份执行命令/usr/sbin/newusers 并且从刚创建的用户user.txt 中导入数据
1
# newusers < user.txt
  • 然后可以执行命令 vipwvi /etc/passwd 检查 /etc/passwd 文件是否已经出现这些用户的数据,并且用户的宿主目录是否已经创建。
  1. 执行/usr/sbin/pwunconv
  • /etc/shadow 产生的 shadow 密码解码,然后回写到 /etc/passwd
  • 并将/etc/shadowshadow密码栏删掉
  • 这是为了方便下一步的密码转换工作,即先取消 shadow password 功能。
1
# pwunconv
  1. 编辑每个用户的密码对照文件
  • 格式为:
1
用户名:密码
  • 实例文件 passwd.txt 内容如下:
1
2
3
4
5
6
user001:123456
user002:123456
user003:123456
user004:123456
user005:123456
user006:123456
  1. 以root 身份执行命令 /usr/sbin/chpasswd
  • 创建用户密码,chpasswd 会将经过 /usr/bin/passwd 命令编码过的密码写入 /etc/passwd 的密码栏。
1
# chpasswd < passwd.txt
  1. 确定密码经编码写入 /etc/passwd 密码栏后
  • 执行命令 /usr/sbin/pwconv 将密码编码为 shadow password,并将结果写入 /etc/shadow
1
# pwconv

这样就完成了大量用户的创建了,之后您可以到/home下检查这些用户宿主目录的权限设置是否都正确,并登录验证用户密码是否正确。

4. 文件权限

  • Linux 系统是一种典型的多用户系统,不同的用户处于不同的地位,拥有不同的权限。
  • 为了保护系统的安全性,Linux 系统对不同的用户访问同一文件(包括目录文件)的权限做了不同的规定。
  • 在 Linux 中我们通常使用以下两个命令来修改文件或目录的所属用户与权限:
    • chown (change ownerp) : 修改所属用户与组。
    • chmod (change mode) : 修改用户的权限。

mark

mark

4.1 文件属性

每个文件的属性由左边第一部分的 10 个字符来确定(如下图)。

mark

mark

  • 从左至右用 0-9 这些数字来表示。

  • 0 位确定文件类型,

  • 1-3 位确定属主(该文件的所有者)拥有该文件的权限。

  • 4-6 位确定属组(所有者的同组用户)拥有该文件的权限

*权限对应 r w x *

  • 其中,第 1、4、7 位表示读权限,如果用 r 字符表示,则有读权限,如果用 - 字符表示,则没有读权限;
  • 2、5、8 位表示写权限,如果用 w 字符表示,则有写权限,如果用 - 字符表示没有写权限;
  • 3、6、9 位表示可执行权限,如果用 x 字符表示,则有执行权限,如果用 - 字符表示,则没有执行权限。
  1. 文件类型

mark

在 Linux 中第一个字符代表这个文件是目录、文件或链接文件等等。

  • 当为 d 则是目录
  • 当为 - 则是文件;
  • 若是 l 则表示为链接文档(link file);
  • 若是 b 则表示为装置文件里面的可供储存的接口设备(可随机存取装置);
  • 若是 c 则表示为装置文件里面的串行端口设备,例如键盘、鼠标(一次性读取装置)。

4.2 文件权限表示方法

mark

4.3 权限的修改

在 Linux 中我们通常使用以下两个命令来修改文件或目录的所属用户与权限:

  • chown (change ownerp) : 修改所属用户与组。
  • chmod (change mode) : 修改用户的权限。

mark

1. chown : 更改属组 属主

  • 对于文件来说,它都有一个特定的所有者,也就是对该文件具有所有权的用户。

  • 同时,在Linux系统中,用户是按组分类的,一个用户属于一个或多个组。

  • 文件所有者以外的用户又可以分为文件所有者的同组用户和其他用户。

  • 因此,Linux系统按文件所有者、文件所有者同组用户和其他用户来规定了不同的文件访问权限。

举例

  1. 新建一个默认的目录mkdir test

mark

  1. 新建user1,user2,user3用户 并且设置组环境
    • useradd user1
    • useradd user2
    • useradd user3

mark

  1. 对目录修改属主和属组
  • 修改属主
    • chown user1 test/
    • ls -ld test/

mark

  • 修改属组
    • chown :group1 test/
    • ls -ld test/

mark

注意:

  • 权限限制是限制非root 用户的 ,即使root用户没有赋予任何权限,还是可以修改文件

2. chgrp : 更改属组

语法:

1
chgrp [-R] 属组名 文件名

参数选项

  • -R:递归更改文件属组,就是在更改某个目录文件的属组时,如果加上-R的参数,那么该目录下的所有文件的属组都会更改。

mark

3. chmod : 更改文件9个属性

  • Linux文件属性有两种设置方法,一种是数字,一种是符号。

  • Linux 文件的基本权限就有九个,

    • 分别是 owner/group/others(拥有者/组/其他) 三种身份
    • 各有自己的 read/write/execute 权限。
  1. 字符修改权限

从之前的介绍中我们可以发现,基本上就九个权限分别是:

  • user:用户
  • group:组
  • others:其他

那么我们就可以使用 u, g, o 来代表三种身份的权限。

此外, a 则代表 all,即全部的身份。读写的权限可以写成 r, w, x,也就是可以使用下表的方式来看:

mark

举例

  • 如果我们需要将文件权限设置为 -rwxr-xr– ,可以使用 chmod u=rwx,g=rx,o=r 文件名 来设定:
1
2
3
4
5
6
#  touch test1    // 创建 test1 文件
# ls -al test1 // 查看 test1 默认权限
-rw-r--r-- 1 root root 0 Nov 15 10:32 test1
# chmod u=rwx,g=rx,o=r test1 // 修改 test1 权限
# ls -al test1
-rwxr-xr-- 1 root root 0 Nov 15 10:32 test1
  • 而如果是要将权限去掉而不改变其他已存在的权限呢?例如要拿掉全部人的可执行权限,则:

    1
    2
    3
    #  chmod  a-x test1
    # ls -al test1
    -rw-r--r-- 1 root root 0 Nov 15 10:32 test1
  1. 数字权限

先复习一下刚刚上面提到的数据:文件的权限字符为: -rwxrwxrwx , 这九个权限是三个三个一组的!其中,我们可以使用数字来代表各个权限,各权限的分数对照表如下:

  • r:4
  • w:2
  • x:1

每种身份(owner/group/others)各自的三个权限(r/w/x)分数是需要累加的,例如当权限为: -rwxrwx— 分数则是:

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

所以等一下我们设定权限的变更时,该文件的权限数字就是 770。变更权限的指令 chmod 的语法是这样的:

1
chmod [-R] xyz 文件或目录

选项与参数:

  • xyz : 就是刚刚提到的数字类型的权限属性,为 rwx 属性数值的相加。
  • -R : 进行递归(recursive)的持续变更,亦即连同次目录下的所有文件都会变更

举例来说,如果要将 .bashrc 这个文件所有的权限都设定启用,那么命令如下:

1
2
3
4
5
[root@www ~]# ls -al .bashrc
-rw-r--r-- 1 root root 395 Jul 4 11:45 .bashrc
[root@www ~]# chmod 777 .bashrc
[root@www ~]# ls -al .bashrc
-rwxrwxrwx 1 root root 395 Jul 4 11:45 .bashrc

那如果要将权限变成 -rwxr-xr– 呢?那么权限的分数就成为 754。

4. 默认文件权限644由来

  1. umask = 0022
  2. 666 - 0022 = 644

mark

mark

注意 :

  1. 文件具体的权限以用户的权限为主

    • 如果发生权限冲突,即有种情况:用户没有权限但是属组有权限,该用户仍然没有权限,但是该组下其他用户是有对应权限的。
  2. 目录的具体权限

    • x 表示可以进入目录的权限
    • 进入目录并且查看 需要 rx权限
    • 进入目录并且删除文件 需要 wx权限

5. 特殊权限

mark

  1. SUID : 获取属主权限
    • 比如用户修改自己的密码

mark

  1. SGID : 文件共享时,权限改为该目录的属组
  2. SBIT : 防止自己的文件被其他普通用户误删掉

mark

  • 增加特殊权限
    • SUID : chmod 4xxx xxx为原有的权限
    • SBIT : chmod 1xxx xxx为原有的权限

5. 网络管理

mark

5.1 网络状态的查看

mark

  1. net-tools 适用于 centos7 之前的系统
  2. iproute2 适用于 centos7 以后的系统

1. ifconfig

mark

  1. if = interface缩写(if)
  2. 第一块网卡的不同命名
    • 对于服务器来说 如果服务器很多 那么批量操作就显得不便捷
  3. 普通用户查看 sbin/ifconfig 进行网络查看

注意: 如何重写网卡名回到eth0

mark

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@zhuuu test]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.21.0.6 netmask 255.255.240.0 broadcast 172.21.15.255 # ip地址 子网掩码 广播地址
inet6 fe80::5054:ff:fe02:6706 prefixlen 64 scopeid 0x20<link>
ether 52:54:00:02:67:06 txqueuelen 1000 (Ethernet)
RX packets 3234415 bytes 289214162 (275.8 MiB) # 发送数据包个数 和 大小
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3149017 bytes 549055111 (523.6 MiB) # 接受数据包个数 和 大小
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

# lo 本地环回
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 4450 bytes 218920 (213.7 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 4450 bytes 218920 (213.7 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

2. mii-tool

mark

注意:

  • 虚拟机/云服务器不支持此命令查看

mark

3. route

mark

  1. route 中的 ip 会变成域名
  2. route -n 不会反解ip 为域名

mark

5.2 网络配置的修改

1. ifup ifdown

mark

  1. 启动关闭指定网卡

    1
    2
    # ifconfig eth0 down
    # ifconfig eth0 up

2. 网关配置

mark

mark

指定明细路由

  1. 指定走特定ip 使用特定的路由

mark

mark

  1. 指定走特定的网段 使用特定的路由

mark

3. ip 命令

mark

注意:

  • 云服务器暂时不需要改动,因为改动可能就连不上了

5.3 网络故障的排除(服务上线网络问题)

mark

1. ping

  • 执行ping指令会使用ICMP传输协议,发出要求回应的信息,若远端主机的网络功能没有问题,就会回应该信息,因而得知该主机运作正常。
1
ping [-dfnqrRv][-c<完成次数>][-i<间隔秒数>][-I<网络界面>][-l<前置载入>][-p<范本样式>][-s<数据包大小>][-t<存活数值>][主机名称或IP地址]

参数说明

  • -d 使用Socket的SO_DEBUG功能。
  • -c<完成次数> 设置完成要求回应的次数。
  • -f 极限检测。
  • -i<间隔秒数> 指定收发信息的间隔时间。
  • -I<网络界面> 使用指定的网络接口送出数据包。
  • -l<前置载入> 设置在送出要求信息之前,先行发出的数据包。
  • -n 只输出数值。
  • -p<范本样式> 设置填满数据包的范本样式。
  • -q 不显示指令执行过程,开头和结尾的相关信息除外。
  • -r 忽略普通的Routing Table,直接将数据包送到远端主机上。
  • -R 记录路由过程。
  • -s<数据包大小> 设置数据包的大小。
  • -t<存活数值> 设置存活数值TTL的大小。
  • -v 详细显示指令的执行过程。

举例子

  1. 检测是否与主机连通
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# ping www.w3cschool.cc //ping主机
PING aries.m.alikunlun.com (114.80.174.110) 56(84) bytes of data.
64 bytes from 114.80.174.110: icmp_seq=1 ttl=64 time=0.025 ms
64 bytes from 114.80.174.110: icmp_seq=2 ttl=64 time=0.036 ms
64 bytes from 114.80.174.110: icmp_seq=3 ttl=64 time=0.034 ms
64 bytes from 114.80.174.110: icmp_seq=4 ttl=64 time=0.034 ms
64 bytes from 114.80.174.110: icmp_seq=5 ttl=64 time=0.028 ms
64 bytes from 114.80.174.110: icmp_seq=6 ttl=64 time=0.028 ms
64 bytes from 114.80.174.110: icmp_seq=7 ttl=64 time=0.034 ms
64 bytes from 114.80.174.110: icmp_seq=8 ttl=64 time=0.034 ms
64 bytes from 114.80.174.110: icmp_seq=9 ttl=64 time=0.036 ms
64 bytes from 114.80.174.110: icmp_seq=10 ttl=64 time=0.041 ms

--- aries.m.alikunlun.com ping statistics ---
10 packets transmitted, 30 received, 0% packet loss, time 29246ms
rtt min/avg/max/mdev = 0.021/0.035/0.078/0.011 ms

//需要手动终止Ctrl+C
  1. 指定接收包的次数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # ping -c 2 www.w3cschool.cc
    PING aries.m.alikunlun.com (114.80.174.120) 56(84) bytes of data.
    64 bytes from 114.80.174.120: icmp_seq=1 ttl=54 time=6.18 ms
    64 bytes from 114.80.174.120: icmp_seq=2 ttl=54 time=15.4 ms

    --- aries.m.alikunlun.com ping statistics ---
    2 packets transmitted, 2 received, 0% packet loss, time 1016ms
    rtt min/avg/max/mdev = 6.185/10.824/15.464/4.640 ms

    //收到两次包后,自动退出
  1. 多参数使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # ping -i 3 -s 1024 -t 255 g.cn //ping主机
    PING g.cn (203.208.37.104) 1024(1052) bytes of data.
    1032 bytes from bg-in-f104.1e100.net (203.208.37.104): icmp_seq=0 ttl=243 time=62.5 ms
    1032 bytes from bg-in-f104.1e100.net (203.208.37.104): icmp_seq=1 ttl=243 time=63.9 ms
    1032 bytes from bg-in-f104.1e100.net (203.208.37.104): icmp_seq=2 ttl=243 time=61.9 ms

    --- g.cn ping statistics ---
    3 packets transmitted, 3 received, 0% packet loss, time 6001ms
    rtt min/avg/max/mdev = 61.959/62.843/63.984/0.894 ms, pipe 2
    [root@linux ~]#

    //-i 3 发送周期为 3秒 -s 设置发送包的大小 -t 设置TTL值为 255

2. traceroute

  • Linux traceroute命令用于显示数据包到主机间的路径。
  • traceroute指令让你追踪网络数据包的路由途径,预设数据包大小是40Bytes,用户可另行设置。
1
traceroute [-dFlnrvx][-f<存活数值>][-g<网关>...][-i<网络界面>][-m<存活数值>][-p<通信端口>][-s<来源地址>][-t<服务类型>][-w<超时秒数>][主机名称或IP地址][数据包大小]

参数说明

  • -d 使用Socket层级的排错功能。
  • -f<存活数值> 设置第一个检测数据包的存活数值TTL的大小。
  • -F 设置勿离断位。
  • -g<网关> 设置来源路由网关,最多可设置8个。
  • -i<网络界面> 使用指定的网络界面送出数据包。
  • -I 使用ICMP回应取代UDP资料信息。
  • -m<存活数值> 设置检测数据包的最大存活数值TTL的大小。
  • -n 直接使用IP地址而非主机名称。
  • -p<通信端口> 设置UDP传输协议的通信端口。
  • -r 忽略普通的Routing Table,直接将数据包送到远端主机上。
  • -s<来源地址> 设置本地主机送出数据包的IP地址。
  • -t<服务类型> 设置检测数据包的TOS数值。
  • -v 详细显示指令的执行过程。
  • -w<超时秒数> 设置等待远端主机回报的时间。
  • -x 开启或关闭数据包的正确性检验。

举例子:

  1. 追踪到 百度页面 等待时间1秒

traceroute -w 1 www.baidu.com

mark

3. mtr

  • 输入mtr后进入该界面
  • 显示主机之间的通信(常用)

mark

4. nslookup

  • 将域名解析为 ip 地址

mark

5. telnet

  • Linux telnet命令用于远端登入。
  • 执行telnet指令开启终端机阶段作业,并登入远端主机。
1
telnet [-8acdEfFKLrx][-b<主机别名>][-e<脱离字符>][-k<域名>][-l<用户名称>][-n<记录文件>][-S<服务类型>][-X<认证形态>][主机名称或IP地址<通信端口>]

参数说明

  • -8 允许使用8位字符资料,包括输入与输出。
  • -a 尝试自动登入远端系统。
  • -b<主机别名> 使用别名指定远端主机名称。
  • -c 不读取用户专属目录里的.telnetrc文件。
  • -d 启动排错模式。
  • -e<脱离字符> 设置脱离字符。
  • -E 滤除脱离字符。
  • -f 此参数的效果和指定”-F”参数相同。
  • -F 使用Kerberos V5认证时,加上此参数可把本地主机的认证数据上传到远端主机。
  • -k<域名> 使用Kerberos认证时,加上此参数让远端主机采用指定的领域名,而非该主机的域名。
  • -K 不自动登入远端主机。
  • -l<用户名称> 指定要登入远端主机的用户名称。
  • -L 允许输出8位字符资料。
  • -n<记录文件> 指定文件记录相关信息。
  • -r 使用类似rlogin指令的用户界面。
  • -S<服务类型> 设置telnet连线所需的IP TOS信息。
  • -x 假设主机有支持数据加密的功能,就使用它。
  • -X<认证形态> 关闭指定的认证形态。

举例子:

  1. 查看端口是否畅通

mark

telnet 域名/ip 端口号

  1. 退出telnet
    • ctrl + ]
    • 再次输入quit

6. tcpdump 网络抓包

  • Linux tcpdump命令用于倾倒网络传输数据。
  • 执行tcpdump指令可列出经过指定网络界面的数据包文件头
  • Linux操作系统中,你必须是系统管理员。
1
tcpdump [-adeflnNOpqStvx][-c<数据包数目>][-dd][-ddd][-F<表达文件>][-i<网络界面>][-r<数据包文件>][-s<数据包大小>][-tt][-T<数据包类型>][-vv][-w<数据包文件>][输出数据栏位]

参数说明

  • -a 尝试将网络和广播地址转换成名称。
  • -c<数据包数目> 收到指定的数据包数目后,就停止进行倾倒操作。
  • -d 把编译过的数据包编码转换成可阅读的格式,并倾倒到标准输出。
  • -dd 把编译过的数据包编码转换成C语言的格式,并倾倒到标准输出。
  • -ddd 把编译过的数据包编码转换成十进制数字的格式,并倾倒到标准输出。
  • -e 在每列倾倒资料上显示连接层级的文件头。
  • -f 用数字显示网际网络地址。
  • -F<表达文件> 指定内含表达方式的文件。
  • -i<网络界面> 使用指定的网络截面送出数据包。
  • -l 使用标准输出列的缓冲区。
  • -n 不把主机的网络地址转换成名字。
  • -N 不列出域名。
  • -O 不将数据包编码最佳化。
  • -p 不让网络界面进入混杂模式。
  • -q 快速输出,仅列出少数的传输协议信息。
  • -r<数据包文件> 从指定的文件读取数据包数据。
  • -s<数据包大小> 设置每个数据包的大小。
  • -S 用绝对而非相对数值列出TCP关联数。
  • -t 在每列倾倒资料上不显示时间戳记。
  • -tt 在每列倾倒资料上显示未经格式化的时间戳记。
  • -T<数据包类型> 强制将表达方式所指定的数据包转译成设置的数据包类型。
  • -v 详细显示指令执行过程。
  • -vv 更详细显示指令执行过程。
  • -x 用十六进制字码列出数据包资料。
  • -w<数据包文件> 把数据包数据写入指定的文件。

举例

  1. 抓取80端口 不显示域名 的所有数据包

tcpdump -i any -n port 80

mark

  1. 抓取特定主机 不显示域名 的所有数据包

tcpdump -i any -n host 10.0.0.1

  1. 同时抓取ip + port 的数据包

tcpdump -i any -n host 10.0.0.1 and port 80

  1. 抓取数据包 并 保存成为日志文件

tcpdump -i any -n host 10.0.0.1 and port 80 -w 指定路径

7. netstat

  • Linux netstat 命令用于显示网络状态。
  • 利用 netstat 指令可让你得知整个 Linux 系统的网络情况。
1
netstat [-acCeFghilMnNoprstuvVwx][-A<网络类型>][--ip]

参数说明

  • -a或–all 显示所有连线中的Socket。
  • -A<网络类型>或–<网络类型> 列出该网络类型连线中的相关地址。
  • -c或–continuous 持续列出网络状态。
  • -C或–cache 显示路由器配置的快取信息。
  • -e或–extend 显示网络其他相关信息。
  • -F或–fib 显示FIB。
  • -g或–groups 显示多重广播功能群组组员名单。
  • -h或–help 在线帮助。
  • -i或–interfaces 显示网络界面信息表单。
  • -l或–listening 显示监控中的服务器的Socket。
  • -M或–masquerade 显示伪装的网络连线。
  • -n或–numeric 直接使用IP地址,而不通过域名服务器。
  • -N或–netlink或–symbolic 显示网络硬件外围设备的符号连接名称。
  • -o或–timers 显示计时器。
  • -p或–programs 显示正在使用Socket的程序识别码和程序名称。
  • -r或–route 显示Routing Table。
  • -s或–statistics 显示网络工作信息统计表。
  • -t或–tcp 显示TCP传输协议的连线状况。
  • -u或–udp 显示UDP传输协议的连线状况。
  • -v或–verbose 显示指令执行过程。
  • -V或–version 显示版本信息。
  • -w或–raw 显示RAW传输协议的连线状况。
  • -x或–unix 此参数的效果和指定”-A unix”参数相同。
  • –ip或–inet 此参数的效果和指定”-A inet”参数相同。

举例

  1. 不显示域名 监听 tcp 的进程

mark

8. ss

  • 另外一种格式的netstat

mark

5.4 网络服务管理(保存网络配置)

  1. 网络服务管理命令

mark

  • SysV : centos 7 之前使用
  • sytemd : centos 7 之后使用
  1. 网络配置文件

mark

1. 查看网卡

service network status : 查看网卡状态

mark

service network start : 重新还原默认配置

2. NetworkManager

  1. 首先需要禁用上述第一点的 network
    • chkconfig --list network : 查看network 状态
    • chkconfig --level 2345 network off : 禁用network

mark

  1. NetworkManger 的作用
    • 个人电脑 : 自动连接Wi-fi网络
    • 服务器 : 沿用network
      • chkconfig --level 2345 network on
  1. 禁用NetworkManger
    • systemctl disable NetworkManager
    • systemctl enable NetworkManager

3. 网卡配置文件修改(network-scripts)

  • cd /etc/sysconfig/network-scripts/
1
2
3
4
5
6
[root@zhuuu ~]# cd /etc/sysconfig/network-scripts/
[root@zhuuu network-scripts]# ls
ifcfg-eth0 ifdown-eth ifdown-post ifdown-Team ifup-aliases ifup-ipv6 ifup-post ifup-Team init.ipv6-global
ifcfg-lo ifdown-ippp ifdown-ppp ifdown-TeamPort ifup-bnep ifup-isdn ifup-ppp ifup-TeamPort network-functions
ifdown ifdown-ipv6 ifdown-routes ifdown-tunnel ifup-eth ifup-plip ifup-routes ifup-tunnel network-functions-ipv6
ifdown-bnep ifdown-isdn ifdown-sit ifup ifup-ippp ifup-plusb ifup-sit ifup-wireless route6-eth0

举例子

  1. vim ifcfg-eth0 : 默认动态ip配置的网卡

mark

  1. 静态ip配置修改(重点)
    • 修改设置生效 : systemctl restart NetworkManager.service
    • 修改设置生效 : service network restart

mark

4. host 修改

  1. hostname : 查看自己的主机名
  2. 临时修改hostname 修改后的主机名
  3. 永久修改hostnamectl set-hostname 修改后的主机名

注意 : 主机名一旦更改,有其他的配置也需要同时修改

  • vim /etc/hosts
  • 加入127.0.0.1 修改后的主机名

6. 软件安装

mark

  • redhat,centos : rpm 包
  • yum : 仓库

6.1 软件包的管理器

mark

  • rpm : centos redhat
  • apt : debian ubuntu

6.2 rpm

  • Linux rpm 命令用于管理套件。
  • rpm(英文全拼:redhat package manager) 原本是 Red Hat Linux 发行版专门用来管理 Linux 各项套件的程序,由于它遵循 GPL 规则且功能强大方便,因而广受欢迎。逐渐受到其他发行版的采用。RPM 套件管理方式的出现,让 Linux 易于安装,升级,间接提升了 Linux 的适用度。

mark

1
rpm [-acdhilqRsv][-b<完成阶段><套间档>+][-e<套件挡>][-f<文件>+][-i<套件档>][-p<套件档>+][-U<套件档>][-vv][--addsign<套件档>+][--allfiles][--allmatches][--badreloc][--buildroot<根目录>][--changelog][--checksig<套件档>+][--clean][--dbpath<数据库目录>][--dump][--excludedocs][--excludepath<排除目录>][--force][--ftpproxy<主机名称或IP地址>][--ftpport<通信端口>][--help][--httpproxy<主机名称或IP地址>][--httpport<通信端口>][--ignorearch][--ignoreos][--ignoresize][--includedocs][--initdb][justdb][--nobulid][--nodeps][--nofiles][--nogpg][--nomd5][--nopgp][--noorder][--noscripts][--notriggers][--oldpackage][--percent][--pipe<执行指令>][--prefix<目的目录>][--provides][--queryformat<档头格式>][--querytags][--rcfile<配置档>][--rebulid<套件档>][--rebuliddb][--recompile<套件档>][--relocate<原目录>=<新目录>][--replacefiles][--replacepkgs][--requires][--resign<套件档>+][--rmsource][--rmsource<文件>][--root<根目录>][--scripts][--setperms][--setugids][--short-circuit][--sign][--target=<安装平台>+][--test][--timecheck<检查秒数>][--triggeredby<套件档>][--triggers][--verify][--version][--whatprovides<功能特性>][--whatrequires<功能特性>]

参数说明

  • -a  查询所有套件。
  • -b<完成阶段><套件档>+或-t <完成阶段><套件档>+  设置包装套件的完成阶段,并指定套件档的文件名称。
  • -c  只列出组态配置文件,本参数需配合”-l”参数使用。
  • -d  只列出文本文件,本参数需配合”-l”参数使用。
  • -e<套件档>或–erase<套件档>  删除指定的套件。
  • -f<文件>+  查询拥有指定文件的套件。
  • -h或–hash  套件安装时列出标记。
  • -i  显示套件的相关信息。
  • -i<套件档>或–install<套件档>  安装指定的套件档。
  • -l  显示套件的文件列表。
  • -p<套件档>+  查询指定的RPM套件档。
  • -q  使用询问模式,当遇到任何问题时,rpm指令会先询问用户。
  • -R  显示套件的关联性信息。
  • -s  显示文件状态,本参数需配合”-l”参数使用。
  • -U<套件档>或–upgrade<套件档> 升级指定的套件档。
  • -v  显示指令执行过程。
  • -vv  详细显示指令执行过程,便于排错。
  • -addsign<套件档>+  在指定的套件里加上新的签名认证。
  • –allfiles  安装所有文件。
  • –allmatches  删除符合指定的套件所包含的文件。
  • –badreloc  发生错误时,重新配置文件。
  • –buildroot<根目录>  设置产生套件时,欲当作根目录的目录。
  • –changelog  显示套件的更改记录。
  • –checksig<套件档>+  检验该套件的签名认证。
  • –clean  完成套件的包装后,删除包装过程中所建立的目录。
  • –dbpath<数据库目录>  设置欲存放RPM数据库的目录。
  • –dump  显示每个文件的验证信息。本参数需配合”-l”参数使用。
  • –excludedocs  安装套件时,不要安装文件。
  • –excludepath<排除目录>  忽略在指定目录里的所有文件。
  • –force  强行置换套件或文件。
  • –ftpproxy<主机名称或IP地址>  指定FTP代理服务器。
  • –ftpport<通信端口>  设置FTP服务器或代理服务器使用的通信端口。
  • –help  在线帮助。
  • –httpproxy<主机名称或IP地址>  指定HTTP代理服务器。
  • –httpport<通信端口>  设置HTTP服务器或代理服务器使用的通信端口。
  • –ignorearch  不验证套件档的结构正确性。
  • –ignoreos  不验证套件档的结构正确性。
  • –ignoresize  安装前不检查磁盘空间是否足够。
  • –includedocs  安装套件时,一并安装文件。
  • –initdb  确认有正确的数据库可以使用。
  • –justdb  更新数据库,当不变动任何文件。
  • –nobulid  不执行任何完成阶段。
  • –nodeps  不验证套件档的相互关联性。
  • –nofiles  不验证文件的属性。
  • –nogpg  略过所有GPG的签名认证。
  • –nomd5  不使用MD5编码演算确认文件的大小与正确性。
  • –nopgp  略过所有PGP的签名认证。
  • –noorder  不重新编排套件的安装顺序,以便满足其彼此间的关联性。
  • –noscripts  不执行任何安装Script文件。
  • –notriggers  不执行该套件包装内的任何Script文件。
  • –oldpackage  升级成旧版本的套件。
  • –percent  安装套件时显示完成度百分比。
  • –pipe<执行指令>  建立管道,把输出结果转为该执行指令的输入数据。
  • –prefix<目的目录>  若重新配置文件,就把文件放到指定的目录下。
  • –provides  查询该套件所提供的兼容度。
  • –queryformat<档头格式>  设置档头的表示方式。
  • –querytags  列出可用于档头格式的标签。
  • –rcfile<配置文件>  使用指定的配置文件。
  • –rebulid<套件档>  安装原始代码套件,重新产生二进制文件的套件。
  • –rebuliddb  以现有的数据库为主,重建一份数据库。
  • –recompile<套件档>  此参数的效果和指定”–rebulid”参数类似,当不产生套件档。
  • –relocate<原目录>=<新目录>  把本来会放到原目录下的文件改放到新目录。
  • –replacefiles  强行置换文件。
  • –replacepkgs  强行置换套件。
  • –requires  查询该套件所需要的兼容度。
  • –resing<套件档>+  删除现有认证,重新产生签名认证。
  • –rmsource  完成套件的包装后,删除原始代码。
  • –rmsource<文件>  删除原始代码和指定的文件。
  • –root<根目录>  设置欲当作根目录的目录。
  • –scripts  列出安装套件的Script的变量。
  • –setperms  设置文件的权限。
  • –setugids  设置文件的拥有者和所属群组。
  • –short-circuit  直接略过指定完成阶段的步骤。
  • –sign  产生PGP或GPG的签名认证。
  • –target=<安装平台>+  设置产生的套件的安装平台。
  • –test  仅作测试,并不真的安装套件。
  • –timecheck<检查秒数>  设置检查时间的计时秒数。
  • –triggeredby<套件档>  查询该套件的包装者。
  • –triggers  展示套件档内的包装Script。
  • –verify  此参数的效果和指定”-q”参数相同。
  • –version  显示版本信息。
  • –whatprovides<功能特性>  查询该套件对指定的功能特性所提供的兼容度。
  • –whatrequires<功能特性>  查询该套件对指定的功能特性所需要的兼容度。

举个例子

  1. 安装vim

mark

  1. 查询系统中所有安装的软件包 :rpm -qa
  2. 分屏显示所有安装的软件包 : rpm -qa | more
  3. 查询一个单独的软件包版本 : rpm -q 软件名
  4. 安装软件包 rpm -i 软件名
  5. 卸载软件包 rpm -e 软件名

注意:

  • 查询Linux设备路径 ls -al /dev
  • Linux 光驱 ls -l /dev/sr0
  • 把光驱做成iso 文件 : dd if=/dev/sr0 of=/xxx/xx.iso
  • 挂载光驱 : mount /dev/sr0 /mnt 注:/mnt 是Linux 用来挂载的目录

mark

  • 软件包的依赖问题

mark

6.3 yum

  • yum( Yellow dog Updater, Modified)是一个在 Fedora 和 RedHat 以及 SUSE 中的 Shell 前端软件包管理器。
  • 基于 RPM 包管理,能够从指定的服务器自动下载 RPM 包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖的软体包,无须繁琐地一次次下载、安装。
  • yum 提供了查找、安装、删除某一个、一组甚至全部软件包的命令,而且命令简洁而又好记。
  1. yum仓库

mark

  1. 修改yum 配置文件

mark

mark

  1. yum 常用命令
1
yum [options] [command] [package ...]
  • options:可选,选项包括-h(帮助),-y(当安装过程提示选择全部为 “yes”),-q(不显示安装的过程)等等。
  • command:要进行的操作。
  • package:安装的包名。

mark

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1. 列出所有可更新的软件清单命令:yum check-update

2. 更新所有软件命令:yum update

3. 仅安装指定的软件命令:yum install <package_name>

4. 仅更新指定的软件命令:yum update <package_name>

5. 列出所有可安裝的软件清单命令:yum list

6. 删除软件包命令:yum remove <package_name>

7. 查找软件包命令:yum search <keyword>

8. 清除缓存命令:

yum clean packages: 清除缓存目录下的软件包
yum clean headers: 清除缓存目录下的 headers
yum clean oldheaders: 清除缓存目录下旧的 headers
yum clean, yum clean all (= yum clean packages; yum clean oldheaders) :清除缓存目录下的软件包及旧的 headers

国内yum 源

  • 网易(163)yum源是国内最好的yum源之一 ,无论是速度还是软件版本,都非常的不错。
  • 将yum源设置为163 yum,可以提升软件包安装和更新的速度,同时避免一些常见软件版本无法找到。

安装步骤

  1. 首先备份/etc/yum.repos.d/CentOS-Base.repo
1
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
  1. 下载对应版本 repo 文件, 放入 /etc/yum.repos.d/ (操作前请做好相应备份)
1
2
wget http://mirrors.163.com/.help/CentOS6-Base-163.repo
mv CentOS6-Base-163.repo CentOS-Base.repo
  1. 运行以下命令生成缓存
1
2
yum clean all
yum makecache

mark

6.4 源代码编译安装

  • 适用于YUM上没有的软件包
  1. 举个例子 : 流程

mark

注意:

  1. 如果没有gcc编译器
    • yum install gcc gcc-c++
  2. 缺少库
    • yum install 软件名

6.5 升级内核

mark

  1. 查询内核版本 uname -r

  2. rpm 方式安装和 yum方式安装

  3. 源代码编译方式安装内核

  4. 查看 cpu 核心 lscpu

mark

mark

mark

1. 更新仓库版本内核

  1. yum install epel-release 具有较新软件版本的仓库
  2. yum install kernel 更新仓库中的版本内核

6.6 内核引导 (grub)

1. 修改引导内核

mark

  1. grub2-editenv list : 查看目前引导的内核
  2. grub2-set-default 数字默认引导索引为下标数字的内核
    • 同时可以使用grub2-editenv list : 查看目前引导的内核
    • 通过grep ^menu /boot/grub2/grub.cfg 查看目前grub.cfg中可以引导的内核版本

mark

2. 忘记密码

  1. 进入启动界面 按下E键

mark

  1. 找到图中显示的这一行配置

mark

  1. 添加配置项 rd.break :之后按下ctrl + x 启动

mark

mark

  1. mount -o remount,rw : 从虚拟内存上把root挂载到硬盘上
    • 重新挂载root目录 : chroot /sysroot

mark

mark

  1. 标准输入echo 密码 | passwd --stdin root

mark

以上就是重新设置好了root的密码

注意 : SELinux问题

  • SELinux 会强制校验导致无法正常登陆系统
  • 关闭 SELinux :
    • vim /etc/selinux/config
    • 改为disabled
  • 最后exit 后 reboot重启系统

mark

7. 进程管理

mark

7.1 进程的概念

mark

7.2 进程的查看

mark

1. ps

  • Linux ps (英文全拼:process status)命令用于显示当前进程的状态,类似于 windows 的任务管理器。
1
ps [options] [--help]

参数

ps 的参数非常多, 在此仅列出几个常用的参数并大略介绍含义

  • -A 列出所有的进程
  • -e : -e-A的意思是一样的,即显示有关其他用户进程的信息,包括那些没有控制终端的进程。
  • -ef : -f显示用户id,进程id,父进程id,最近CPU使用情况,进程开始时间等等
  • -eLf : 打印进程信息和其中的线程信息
  1. 分页查看进程

ps -e | more

mark

  1. 常用 ps -ef : 显示所有进程信息,连同命令行

mark

  1. ps -eLf :打印进程和其中线程的信息

2. pstree

  • 打印父子进程的树状形式

mark

3. top

  • Linux top命令用于实时显示 process 的动态。
  • 使用权限:所有使用者。

mark

1
top [-] [d delay] [q] [c] [S] [s] [i] [n] [b]

参数说明

  • d : 改变显示的更新速度,或是在交谈式指令列( interactive command)按 s
  • q : 没有任何延迟的显示速度,如果使用者是有 superuser 的权限,则 top 将会以最高的优先序执行
  • c : 切换显示模式,共有两种模式,一是只显示执行档的名称,另一种是显示完整的路径与名称
  • S : 累积模式,会将己完成或消失的子行程 ( dead child process ) 的 CPU time 累积起来
  • s : 安全模式,将交谈式指令取消, 避免潜在的危机
  • i : 不显示任何闲置 (idle) 或无用 (zombie) 的行程
  • n : 更新的次数,完成后将会退出 top
  • b : 批次档模式,搭配 “n” 参数一起使用,可以用来将 top 的结果输出到档案内
  • p : 显示指定的进程信息

举例子

  1. 显示指定的进程信息
1
2
3
# top -p 139

//显示进程号为139的进程信息,CPU、内存占用率等

7.3 进程的控制

mark

1. 优先级(nice/renice)

  • 设置优先级 nice -n 优先级(默认是0) 需要执行的文件

mark

  • 调整nice 值 : renice -n 15 进程号

mark

2. 后台前台运行切换 (jobs)

  1. *后台运行程序 * shift + 7:&

mark

  1. 调回到前台 jobs

mark

  • jobs : 查看后台进程
  • fg 索引号 : 调回到前台运行
  • bg 索引号 : 后台运行
  1. 前台再放回到后台挂起
    • ctrl + z
  • 这里再次top 进程号

mark

  • 可以发现进程还在后台 只不过是挂起状态
  1. 后台挂起恢复运行
    • 同上第2点

mark

7.4 进程通信(信号)

mark

  • Linux kill 命令用于删除执行中的程序或工作。

  • kill 可将指定的信息送至程序。预设的信息为 SIGTERM(15),可将指定程序终止。

  • 若仍无法终止该程序,可使用 SIGKILL(9) 信息尝试强制删除程序

  • 程序或工作的编号可利用 ps 指令或 jobs 指令查看。

  1. kill -l : 查看所有支持的信号

mark

  1. ctrl + c = SIGINT : 2号信号
  2. kill -9 进程号9号信号

7.5 守护进程

mark

  • 守护进程不需要自己启动
  • 守护进程占用的目录是根目录
  • 输出到指定的日志文件中

1. nohup(这个不是守护进程)

  • nohup 英文全称 no hang up(不挂起),用于在系统后台不挂断地运行命令,退出终端不会影响程序的运行。

  • nohup 命令,在默认情况下(非重定向时),会输出一个名叫 nohup.out 的文件到当前目录下,如果当前目录的 nohup.out 文件不可写,输出重定向到 $HOME/nohup.out 文件中

作用 : 不响应挂起的信号

1
nohup Command [ Arg … ] [ & ]

参数说明:

Command:要执行的命令。

Arg:一些参数,可以指定输出文件。

&:让命令在后台执行,终端退出后命令仍旧执行。

举个例子

  1. nohup tail -f /var/log/messaages &

mark

mark

  1. 本进程打印的内容 都 存到当前目录的 nohup.out 文件中

  2. 关闭当前shell , 可以看到的是: 之前nohup的进程的父进程变成了1号进程(孤儿进程)

mark

注意 :上述 tail 进程和 守护进程的区别

  • 输出文件的不同
  • 挂载的目录不同
  • 但都是由1号进程收留

nohup 进程输出目录 : tail 进程举例

mark

守护进程输出目录:sshd进程举例

mark

mark

2. screen (第三方工具)

mark

  • Linux screen命令用于多重视窗管理程序。
  • screen为多重视窗管理程序。此处所谓的视窗,是指一个全屏幕的文字模式画面。通常只有在使用telnet登入主机或是使用老式的终端机时,才有可能用到screen程序。
  • 作用 : 在进行终端操作的时候,先进入screen 环境中 ,即使网络断开了,下次登录还可以恢复工作现场,并且程序还在执行。(规避网络中断)
1
screen [-AmRvx -ls -wipe][-d <作业名称>][-h <行数>][-r <作业名称>][-s <shell>][-S <作业名称>]

参数说明

  • -A  将所有的视窗都调整为目前终端机的大小。
  • -d<作业名称>  将指定的screen作业离线。
  • -h<行数>  指定视窗的缓冲区行数。
  • -m  即使目前已在作业中的screen作业,仍强制建立新的screen作业。
  • -r<作业名称>  恢复离线的screen作业。
  • -R/r  先试图恢复离线的作业。若找不到离线的作业,即建立新的screen作业。
  • -s  指定建立新视窗时,所要执行的shell。
  • -S<作业名称>  指定screen作业的名称。
  • -v  显示版本信息。
  • -x  恢复之前离线的screen作业。
  • -ls或–list  显示目前所有的screen作业。
  • -wipe  检查目前所有的screen作业,并删除已经无法使用的screen作业。

退出Screen

  • ctrl + a + d

举例子

  1. 安装screen
    • yum install screen

mark

  1. 运行 tail -f /var/log/messages
  2. 退出 ctrl + a + d
  1. 恢复screen
    • 首先查看screen 列表 screen -ls
    • 通过 screen -r + 序号 恢复

mark

  1. 取消当前screen: exit

3. 守护进程日志文件

  1. 系统日志位置 /var/log

mark

需要注意的日志文件

  • 常规系统日志文件 : /var/log/messages

  • 内核相关日志信息 : /var/log/dmesg

  • 系统安全日志 : /var/log/secure

  • 周期性计划任务日志 : /var/log/cron

7.6 systemctl (服务管理工具)

mark

  • systemctlservice 的升级版本
  • systemctl启动脚本 比 service启动脚本复杂,但同时更容易进行管理

1. service

举例对比

  1. service 启动脚本
  • network service 脚本存放位置 /etc/init.d
  • vim network

mark

  1. systemctl 启动脚本
  • sshd service 脚本存放位置/usr/lib/systemd/system/

  • vim sshd.service

mark

  1. service : 启动级别
    • chkconfig --list
    • init 无法被 kill -9 杀掉 ,所以如下几种级别可以实现

mark

  • init 0 : 关机

  • init 6: 重启

  • init 1 : 单用户 (重置密码用)

  • init 2 : 不带网络的多用户模式

  • init 3 : 字符模式

  • init 5 : 图形模式

  • init 4 : 未使用

2. systemctl

mark

举个例子 : 重启sshd.service 服务

  • systemctl restart sshd.service
  • systemctl status sshd.service

mark

  1. 关于 enable 和 disable
  • 随开机一起启动 关闭
  1. systemctl : 服务级别问题
  • 存放位置 : /lib/systemd/system
  • ls *.target : 对应的符号链接
  • ls -ld runlevel*.target
1
2
3
4
5
6
7
8
[root@zhuuu system]# ls -ld runlevel*.target
lrwxrwxrwx 1 root root 15 Sep 2 14:22 runlevel0.target -> poweroff.target
lrwxrwxrwx 1 root root 13 Sep 2 14:22 runlevel1.target -> rescue.target
lrwxrwxrwx 1 root root 17 Sep 2 14:22 runlevel2.target -> multi-user.target
lrwxrwxrwx 1 root root 17 Sep 2 14:22 runlevel3.target -> multi-user.target
lrwxrwxrwx 1 root root 17 Sep 2 14:22 runlevel4.target -> multi-user.target
lrwxrwxrwx 1 root root 16 Sep 2 14:22 runlevel5.target -> graphical.target
lrwxrwxrwx 1 root root 13 Sep 2 14:22 runlevel6.target -> reboot.target
  1. 当前服务所在的级别
  • systemlctl get-default : 查看当前服务所在级别
1
2
[root@zhuuu system]# systemctl get-default
multi-user.target
  • systemlctl set-default : 设置下次默认启动服务所在级别

mark

  1. 安排服务启动的顺序

举个例子

  • sshd service 脚本存放位置/usr/lib/systemd/system/

  • vim sshd.service

mark

  1. 新增Requires = xxx.service
  2. 在 After中添加 新的xxx.service

mark

7.7 SELinux (安全组件)

mark

  • 自主访问控制 :通过用户权限进行控制
  • 强制访问控制 :给用户 进程 文件 打标签,三个标签如果对得上就可以访问系统 控制文件

注意 :

  • 一般生产环境中 SELinux 是关闭的
  • 因为 SELinux 是会影响系统性能的

三种状态

  • enforcing
  • permissive
  • disabled
  1. 设置Selinux 运行状态
    • vim /etc/selinux/config

mark

  1. 从enforcing 临时变为 permissive
    • setenforce 0
  1. 查看标签
  • ps -Z : 查看进程标签

mark

  • id -Z : 查看用户标签

mark

  • ls -Z : 查看文件标识

mark

8. 内存和磁盘管理

mark

  • 本章节有以下内容
    • 内存和磁盘使用率的查看
    • ext4 文件系统 (centos 7 之后是xfs)
    • 磁盘配额的使用
    • 磁盘的分区和挂载
    • 交换分区的查看和创建
    • 软件RAID的使用
    • 逻辑卷管理
    • 系统综合状态查看

8.1 内存和磁盘使用率查看

  1. 内存使用率

mark

  1. 磁盘使用率

mark

1. free

  • Linux free命令用于显示内存状态。

  • free指令会显示内存的使用情况,包括实体内存,虚拟的交换文件内存,共享内存区段,以及系统核心使用的缓冲区等。

1
free [-bkmotV][-s <间隔秒数>]

参数说明

  • -b 以Byte为单位显示内存使用情况。

  • -k 以KB为单位显示内存使用情况。

  • -m  以MB为单位显示内存使用情况。

  • -g 以 GB为单位显示内容使用情况

  • -o  不显示缓冲区调节列。
  • -s<间隔秒数>  持续观察内存使用状况。
  • -t  显示内存总和列。
  • -V  显示版本信息。

注意 :

  • 如果要显示以某个单位的内存情况 ,使用下一级单位防止被向下取整

mark

  • swap 对冲区 : 当内存不够用的时候,可以将磁盘上空间先拿来顶用(最好不要swap)
    • Linux 机制 : 如果内存不够用 同时没有swap 的时候,内核会随机杀掉占用内存大的进程

2. top

  • 也可以动态的查看内存使用

mark

3. fdisk

  • Linux fdisk是一个创建和维护分区表的程序,它兼容DOS类型的分区表、BSD或者SUN类型的磁盘列表。
  • 既可以分区 又可以查看磁盘(尽量生产环境不要用)

mark

磁盘分类 : b 块设备

  • 可插拔磁盘 : /dev/sda /dev/sdb ..... (一般为SATA/USB接口硬盘)
  • 云主机磁盘 : /dev/vda

mark

mark

  • 主设备号表示 : 磁盘使用的是什么驱动程序
  • 从设备号表示 : 访问的地址

举个例子

  • fdisk -l : 查看磁盘使用情况
mark

4. parted -l(功能更完善)

  • 作用同 fdisk -l
  • 作用比 fdisk 更为完善

mark

5. df

  • Linux df(英文全拼:disk free) 命令用于显示目前在 Linux 系统上的文件系统磁盘使用情况统计。

举个例子

  1. -h选项,通过它可以产生可读的格式df命令的输出:
1
2
3
4
5
6
7
# df -h 
Filesystem Size Used Avail Use% Mounted on
/dev/sda6 29G 4.2G 23G 16% /
udev 1.5G 4.0K 1.5G 1% /dev
tmpfs 604M 892K 603M 1% /run
none 5.0M 0 5.0M 0% /run/lock
none 1.5G 156K 1.5G 1% /run/shm

我们可以看到输出显示的数字形式的’G’(千兆字节),”M”(兆字节)和”K”(千字节)。

这使输出容易阅读和理解,从而使显示可读的。请注意,第二列的名称也发生了变化,为了使显示可读的”大小”。

  1. 显示文件系统的磁盘使用情况统计
1
2
3
4
5
6
7
# df 
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda6 29640780 4320704 23814388 16% /
udev 1536756 4 1536752 1% /dev
tmpfs 617620 888 616732 1% /run
none 5120 0 5120 0% /run/lock
none 1544044 156 1543888 1% /run/shm
  • 第一列指定文件系统的名称,

  • 第二列指定一个特定的文件系统1K-块1K是1024字节为单位的总内存。用和可用列正在使用中,分别指定的内存量。

  • 使用列指定使用的内存的百分比,而最后一栏”安装在”指定的文件系统的挂载点。

6. du

  • Linux du (英文全拼:disk usage)命令用于显示目录或文件的大小。
  • du 会显示指定的目录或文件所占用的磁盘空间。
1
du [-abcDhHklmsSx][-L <符号连接>][-X <文件>][--block-size][--exclude=<目录或文件>][--max-depth=<目录层数>][--help][--version][目录或文件]

参数说明

  • -a或-all 显示目录中个别文件的大小。
  • -b或-bytes 显示目录或文件大小时,以byte为单位。
  • -c或–total 除了显示个别目录或文件的大小外,同时也显示所有目录或文件的总和。
  • -D或–dereference-args 显示指定符号连接的源文件大小。
  • -h或–human-readable 以K,M,G为单位,提高信息的可读性。
  • -H或–si 与-h参数相同,但是K,M,G是以1000为换算单位。
  • -k或–kilobytes 以1024 bytes为单位。
  • -l或–count-links 重复计算硬件连接的文件。
  • -L<符号连接>或–dereference<符号连接> 显示选项中所指定符号连接的源文件大小。
  • -m或–megabytes 以1MB为单位。
  • -s或–summarize 仅显示总计。
  • -S或–separate-dirs 显示个别目录的大小时,并不含其子目录的大小。
  • -x或–one-file-xystem 以一开始处理时的文件系统为准,若遇上其它不同的文件系统目录则略过。
  • -X<文件>或–exclude-from=<文件> 在<文件>指定目录或文件。
  • –exclude=<目录或文件> 略过指定的目录或文件。
  • –max-depth=<目录层数> 超过指定层数的目录后,予以忽略。
  • –help 显示帮助。
  • –version 显示版本信息。

注意 : du 和 ls 查出来文件大小的区别

mark

根本原因 : 文件存在空洞( 比如 创建30G的虚拟机 真正占用大小只有10G)


空洞文件举例

  1. 创建普通文件 : dd if=输入文件 bs=4M count=10 of=输出文件 (bs count 都是参数 )
    • bs 表示块大小
    • count表示写入几次
    • 这里使用 :dd if=/dev/zero bs=4M count=10 of=afile
mark
  1. 分别查看 du ls 大小
  • du -h afile
  • ls -lh afile

mark

  1. 创建空洞文件
    • dd if=/dev/zero bs=4M count=10 seek=20 of=bfile
    • seek = 20 说明跳过20个块 就是写40M然后跳过80M
  1. 分别查看 du ls 大小
    • du -h bfile
    • ls -lh bfile

mark

小结:ls 和 du 统计的大小是不一样的

  • du 统计的是文件的实际大小
  • ls 统计的是文件的大小

8.2 常见的文件系统

mark

  • 插入的硬盘不是立即可以使用的,必须通过某个文件系统对文件进行管理,才能进行文件读写

  • 常见的系统

    • ext4
    • xfs
    • NTFS(Windows常用,Linux需要安装插件)

1. ext4 文件系统

mark

  • 超级块 : 记录了包含了多少个文件(文件总数 ,df 查的就是这个)

  • 超级块副本:保证超级块的还原

  • i 节点 : 记录每一个文件大小 ,文件名称,文件权限,文件编号

  • 数据块 : 链接式的结构,找到i节点就可以找到数据块 (du 查的就是这个)

i 节点示意图

mark

注意

  1. ls -i 可以查看i 节点记录

  2. 文件名记录在了父目录的节点,而不是记录在自己这里

  3. 文件权限 : 理解rwx

    • 对于普通文件来说 读权限是读数据块(Data Block)内容
    • 对于目录文件来说 读权限是读取目录里的文件名称
  4. 对于上述ls du差异的解读

    • ls 查看的是i 节点里面的信息
    • du 查看的是真正数据块个数的信息

2. touch cp mv vim rm 本质

touch

  1. 默认存储最小的 数据块 大小是4K
1
2
3
4
5
6
7
8
[root@zhuuu ZhuuuTest]# touch afile
[root@zhuuu ZhuuuTest]# ls -li afile
794582 -rw-r--r--. 1 root root 0 Dec 28 15:46 afile
[root@zhuuu ZhuuuTest]# echo 123 > afile
[root@zhuuu ZhuuuTest]# du -h afile
4.0K afile
[root@zhuuu ZhuuuTest]# ls -li afile
794582 -rw-r--r--. 1 root root 4 Dec 28 15:47 afile

注:

  • 当存储大量小文件 ,Linux是如何避免磁盘浪费的

cp

  1. cp 本质是创建了新的文件,相当于是深拷贝(修改一个文件,另外一个文件不会有变化)
1
2
3
4
[root@zhuuu ZhuuuTest]# cp afile afile2
[root@zhuuu ZhuuuTest]# ls -li afile*
794582 -rw-r--r--. 1 root root 4 Dec 28 15:47 afile
794583 -rw-r--r--. 1 root root 4 Dec 28 15:52 afile2
  1. 可以看到上面的是 一个文件 i 节点编号是794582 ,另外一个节点的编号是794583

mv

  1. mv 操作: 虽然mv操作后文件名称变了,但是文件的i 节点编号还是没变
1
2
3
4
[root@zhuuu ZhuuuTest]# mv afile2 afile3
[root@zhuuu ZhuuuTest]# ls -li afile*
794582 -rw-r--r--. 1 root root 4 Dec 28 15:47 afile
794583 -rw-r--r--. 1 root root 4 Dec 28 15:52 afile3
  1. 本质 : 只是改了 目录里面 i节点的对应关系

注:

  • 如果mv 移动到其他的位置 ,那么目录 i节点 数据块都要发生变化
  • 其他位置是指
    • 除当前文件系统的区域
    • 新的分区

vim

  1. vim 默认写入数据会改变 i 节点的信息
1
2
3
4
5
6
[root@zhuuu ZhuuuTest]# vim afile4
[root@zhuuu ZhuuuTest]# ls -li afile4
794584 -rw-r--r--. 1 root root 11 Dec 28 15:59 afile4
[root@zhuuu ZhuuuTest]# vim afile4
[root@zhuuu ZhuuuTest]# ls -li afile4
794586 -rw-r--r--. 1 root root 17 Dec 28 15:59 afile4
  1. vim 编辑的文件会默认生成一个.swap文件

rm

  1. 本质 : 让文件名和 i 节点的链接断开
  2. 文件恢复的秘密 : 因为rm 本质只是让链接断开
    • 此时可以立即断电,扫描磁盘中的i节点和数据块 进行数据恢复
    • 断开链接的好处 : 删除无论多大的文件,时间都是一样的

3. 符号链接和硬链接

ln : 硬链接

  1. ln 命令可以恢复 rm 断开的 i 节点链接
1
2
3
4
[root@zhuuu ZhuuuTest]# ln afile bfile
[root@zhuuu ZhuuuTest]# ls -li afile bfile
794582 -rw-r--r--. 2 root root 4 Dec 28 15:47 afile
794582 -rw-r--r--. 2 root root 4 Dec 28 15:47 bfile

mark

注:

  • ln 链接后的文件,链接的都是同一个文件,无论对哪个文件做改变,两个文件都会同时变化
  • ln 的 link 是不能跨越文件系统的

软链接 : 符号链接

  1. 使用的是ln -s

  2. 符号链接并不是同一个文件, i 节点不同

1
2
3
4
[root@zhuuu ZhuuuTest]# ln -s afile aafile
[root@zhuuu ZhuuuTest]# ls -li afile aafile
794584 lrwxrwxrwx. 1 root root 5 Dec 28 16:15 aafile -> afile
794582 -rw-r--r--. 1 root root 4 Dec 28 15:47 afile
  1. 符号链接 : 记录的是文件的路径

  2. lrwxrwxrwx 权限 前面的l表示是 符号链接

  3. 链接文件的权限是777权限,对链接文件的所有操作都是会执行对原本文件的操作

1
2
3
4
[root@zhuuu ZhuuuTest]# chmod 776 aafile 
[root@zhuuu ZhuuuTest]# ls -li afile aafile
794584 lrwxrwxrwx. 1 root root 5 Dec 28 16:15 aafile -> afile
794582 -rwxrwxrw-. 1 root root 4 Dec 28 15:47 afile

注:

  • 符号链接可以跨不同的系统,跨不同的分区
  • 符号链接和硬链接的区别
    • 符号链接是要创建一个新的文件,记录的是文件的路径
    • 硬链接只是修改了目录的i 节点信息

4. facl (文件访问控制列表)

  1. 查看文件的访问控制列表
1
2
3
4
5
6
7
8
9
10
[root@zhuuu ZhuuuTest]# getfacl afile
# file: afile
# owner: root
# group: root
user::rwx
group::rwx
other::rw-

[root@zhuuu ZhuuuTest]# ls -li afile
794582 -rwxrwxrw-. 1 root root 4 Dec 28 15:47 afile
  1. 赋予特定用户权限
1
2
3
4
5
6
7
8
9
10
11
12
13
[root@zhuuu ZhuuuTest]# useradd zhuuu
[root@zhuuu ZhuuuTest]# setfacl -m u:zhuuu:r afile
[root@zhuuu ZhuuuTest]# ls -l afile
-rwxrwxrw-+ 1 root root 4 Dec 28 15:47 afile
[root@zhuuu ZhuuuTest]# getfacl afile
# file: afile
# owner: root
# group: root
user::rwx
user:zhuuu:r--
group::rwx
mask::rwx
other::rw-

注:

  • setfacl -m u:zhuuu:rw afile 赋予用户权限
  • setfacl -x g:group:r afile 收回用户组权限
  • -rwxrwxrw-+ : + 说明使用了facl ,需使用getfacl afile 进行查看

8.3 分区和挂载

mark

分区的概念

  • 主分区又叫做引导分区,最多只能创建四个。

  • 扩展分区是主分区之外的部分。

    • 扩展分区最多只能有一个(操作系统的限制)
    • 扩展分区无法被格式化
  • 逻辑分区在扩展分区之内可以创建无数个。

    • 逻辑分区的设备名称号码是从5开始(/dev/sd5),因为前面四个都是保留给主要分区或者扩展分区的
    • 逻辑分区可以被格式化

mark

两种磁盘分区表

  • MBR : 分区表大小位512字节,每组分区表仅有16字节而已,会造成无法使用2.2TB以上的磁盘容量
  • GPT :大多会使用所谓的逻辑区块地址(LBA)
    • 使用34个LBA区块来记录分区信息,除了前34个LBA区块来记录信息以外
    • 磁盘的最后34个区块也拿来作为一个备份
    • 从第二块LBA2到LBA33每个LBA都有4组分区记录(512字节),总共可以有4*32 = 128组信息
    • GPT 取消了所谓主,扩展,逻辑分区的概念,每个分区都可以是主要分区
    • fdisk 不支持 GPT,同时启动引导程序grub2以后版本才会支持

1. 进行分区

  1. fdisk /dev/sdc(设备名) : 分区
  2. 获得分区帮助

mark

mark

  1. 新建分区 n
    • 主分区 : 只能扩展4个
      • 早期的MBR(主引导记录)放在磁盘的第一个扇区,这个扇区的大小位512字节
        • 主引导记录:446字节
        • 分区表:64字节(因此最多存放四组分区记录 分别为/dev/sda1-4
    • 扩展分区 : 多余4个分区
      • 需要注意的是,扩展分区的目的是使用额外的扇区来记录分区信息
      • 扩展分区本身并不能进行格式化
    • 服务器一般都是一个主分区
  2. 创建一个50G的分区
    • p 创建主分区
    • p 打印分区情况
    • w 保存分区信息
    • q 不保存退出
    • d 删除当前分区信息

mark

  1. 成功保存

mark

2. 使用分区(mkfs)

  1. 首先根据文件系统去管理分区

mark

  1. mkfs.ext4 /dev/sdc1 : mkfs.文件系统名 设备名

mark

  1. linux 一切皆文件 : 对设备的操作需要挂载磁盘
    • 新建目录 mkdir /mnt/sdc1
  2. 自动检测文件系统挂载mount -t auto(ext4) 需要挂载的设备 挂载的目录

mark

小结

  1. 流程
1
流程 sdc(磁盘)->sdc1(分区)->ext4(文件系统)->mount(挂载)
  1. 挂载后 对目录的操作就是对设备的操作

注意:

  • 如果硬盘大于2T
    • 需要使用parted 命令进行分区
    • 不能使用fdisk
    • 使用方法 :parted 设备名

3. mount (挂载)

  • mount 挂载是放在内存中临时保存的,重启之后就会消失掉
  • 固化(开机自动挂载) : 修改配置文件,开机自动进行挂载
    • 位置存放 vim /etc/fstab

mark

  • 填写方式
    • 第一列 : 设备名
    • 第二列 : 指定要挂载的目录
    • 第三列 : 使用的文件系统
    • 第四列 : (defaults) 给文件系统的权限 : 默认可读可写
    • 第五列,第六列 : 0 0
      • 第一个 0 :dump 硬盘备份 是否要去备份 (现在使用tar 进行备份)
      • 第二个 0 :非正常关机 进行磁盘自检(ext2 ext3)

mark

8.4 用户磁盘配额

1. xfs_quota

  • 用于限制用户/ 用户组使用磁盘的功能

mark

  1. 对分区进行格式化 (-f 强制格式化)mkfs.xfs
  2. 创建挂载目录mkdir -p /mnt/disk1
  3. 挂载设备到目录mount -o uquota,gquota /dev/sdb1 /mnt/disk1
    • 同时支持磁盘配额 (uquota , gquota : 用户磁盘配额和用户组磁盘配额)

mark

  1. 修改权限chomd 1777 /mnt/disk1
  2. 查看用户磁盘配额xfs_quota -x -c 'report -ugibh /mnt/disk1'
    • root 用户不受限制,不要使用root用户查看磁盘配额
    • -ugibh : u:用户 g:用户组 i:i节点 b:块 h:可读
  3. 限制磁盘配额xfs_quota -x -c 'limit -u isoft=5 ihard=10 user1' /mnt/disk1
    • isoft :软限制(i 节点)
    • ihard :硬限制(i 节点)
    • bsoft :软限制(数据块)
    • bhard :硬限制(数据块)

mark

小结

  • 此后,用户1 cd /mnt/disk1 进入该磁盘的时候,会被限制用户磁盘配额

mark

8.5 交换分区 (swap)

  • 作用 :扩充分区两种方式
    • 新的分区
    • 用文件制作swap 分区

1. 分区方式扩充 swap

  1. 查看swap 目前状况 : free -m

mark

  1. 首先对硬盘进行分区 : fdisk 设备

  2. 进行swap格式化 :mkswap /dev/sdd1(分区)

  3. swap 进行挂载 : swapon /dev/sdd1(分区)

  4. swap 进行卸载 : swapoff /dev/sdd1(分区)

再次free -m 进行查看 ,发现swap已经被扩展了

mark

2. 文件方式扩充 swap

  1. 创造空洞文件 :为了制造swap 的空间
    • dd if=/dev/zero bs=4M count=1024 of=/swapfile
  2. 注意 :一定要修改权限 chmod 600 /swapfile
  3. swap 进行挂载 : swapon /swapfile

注意:

  • 以上方式都是临时的
  • 永久需要写入配置文件 : vim /etc/fstab
  • 写入时候发生问题
    • 没有把握 : # 注释掉
    • 写错重启失效 : grub 进行单用户方式,修复/etc/fstab

mark

8.6 RAID

  • RAID : 磁盘阵列

mark

  • RAID常见级别

    • RAID 0 : 将数据写入磁盘 (各写入百分之50,至少两块硬盘)
    • RAID 1 : 镜像方式(自动做备份 ,至少两块硬盘)
    • RAID 5 : RAID 0 和 RAID 1的结合(轮流写入数据和校验) (坏掉两块磁盘数据还是会丢失)
    • RAID 10 : RAID 1 和 RAID 0 的结合(最少准备四块硬盘)(各两块做RAID1,可以坏两块)
  • RAID 实现方式

    • 软件实现 (学习用,CPU会飙升)
    • 硬件实现(工作用)

1. 软件实现

  1. 安装mdadm : yum install mdadm
  2. 创建阵列 :mdadm -C /dev/md0 -a yes -l1 -n2 可以使用的磁盘分区的名称(/dev/sdb1 /dev/sdc1)
    • -C :创建阵列
    • /dev/md0 : 约定俗成的设备名
    • -a yes : 表示同意后面提示
    • -l : RAID级别
      • l1 : RAID1
    • -n2 : 设置几块活动硬盘
  3. 查看阵列 : mdadm —D /dev/md0
  4. 停止RAID : mdadm --stop /dev/md0

mark

mark

注意:

  1. 如果不对/dev/md0 进行数据的读写,而对/dev/sdb1 /dev/sdb2 进行读写

    • 那么RAID就是会失效的
    • 这提供了破坏RAID 的方式,也就是各向磁盘写入数据
  2. RAID 结构 : 使用/dev/md0

    • RAID本质 : 在底层实体硬盘上再叠一层,对虚拟的硬盘进行操作
    • /dev/md0也是所谓的一个逻辑卷
  3. 开机自动加载RAID 磁盘

    • echo DEVICE /dev/sd[b,c]1 >>/etc/mdadm.conf
    • mdadm -Evs >> /etc/mdadm.conf
    • mkfs.xfs /dev/md0
  4. 磁盘的大小最好是一样的

  5. 软件破坏超级块 : 有几块硬盘同时破坏几块

    • dd if=/dev/zero of=/dev/sdb1 bs=1M count=1
    • dd if=/dev/zero of=/dev/sdc1 bs=1M count=1
  6. 硬件破坏RAID : 拔了硬盘就好

8.7 逻辑卷管理

mark

  • 物理设备就是一个 物理卷
  • 逻辑卷使用起来比物理卷更加灵活
    • 逻辑卷是建立在物理设备上的一个虚拟卷
    • LVM将存储虚拟化,使用逻辑卷,你不会受限于物理磁盘的大小,另外,和硬件相关的存储设置被其隐藏,你能不用停止应用或卸载文件系统来调整卷大小或数据迁移.这样能减少操作成本,LVM最大的特点就是可以对磁盘进行动态管理。
    • 因为逻辑卷的大小是可以动态调整的,而且不会丢失现有的数据。如果我们新增加了硬盘,其也不会改变现有上层的逻辑卷。作为一个动态磁盘管理机制,逻辑卷技术大大提高了磁盘管理的灵活性。
  • 作用:
    • 可以将硬盘进行隔离
    • 可以将两个硬盘进行合并
  • 逻辑卷本质 : 在传统硬盘底层再叠一层,以后的操作是对逻辑卷这个虚拟的硬盘进行操作
    • LVM就是通过将底层的物理硬盘抽象的封装起来,然后以逻辑卷的方式呈现给上层应用。
    • 在传统的磁盘管理机制中,我们的上层应用是直接访问文件系统,从而对底层的物理硬盘进行读取
    • 而在LVM中,其通过对底层的硬盘进行封装,当我们对底层的物理硬盘进行操作时,其不再是针对于分区进行操作,而是通过一个叫做逻辑卷的东西来对其进行底层的磁盘管理操作。

  • 传统磁盘操作 : 对硬盘数据进行扩容
    • 首先把数据进行拷走
    • 然后重新对硬盘进行分区
  • 工作当中 :服务器数据是不动的,拷走是不可能的
    • 这么大的数据量移动是不可能的
    • 一般工作中对磁盘空间操作都是只增不减
    • 传统文件系统 : 无法跨硬盘进行使用

补充知识 :

  1. 物理卷(PV, Physical Volume)

    • 物理卷就是指磁盘,磁盘分区或从逻辑上和磁盘分区具有同样功能的设备(如RAID)
    • 是LVM的基本存储逻辑块,但和基本的物理存储介质(如分区、磁盘等)比较,却包含有和LVM相关的管理参数。当前LVM允许你在每个物理卷上保存这个物理卷的0至2份元数据拷贝.默认为1,保存在设备的开始处.为2时,在设备结束处保存第二份备份.
  2. 卷组(VG, Volume Group)

    • LVM卷组类似于非LVM系统中的物理硬盘,其由物理卷组成。能在卷组上创建一个或多个“LVM分区”(逻辑卷),LVM卷组由一个或多个物理卷组成。
  3. 逻辑卷(LV, Logical Volume)

    • LVM的逻辑卷类似于非LVM系统中的硬盘分区,在逻辑卷之上能建立文件系统(比如/home或/usr等)。

mark

前提操作

1:检查系统中是否安装了LVM管理工具

# rpm -qa|grep lvm

1
2
3
4
5
[root@localhost ~]# rpm -qa |grep lvm
lvm2-2.02.177-4.el7.x86_64
llvm-private-5.0.0-3.el7.x86_64
lvm2-libs-2.02.177-4.el7.x86_64
[root@localhost ~]#

2:如果未安装,则使用yum 方式安装

yum install lvm

# rpm -qa|grep lvm

1. 增加逻辑卷

  • 新建逻辑卷
  1. 添加硬盘

    • 查看自己的硬盘 fdisk -l
  2. 创建物理卷

    • pvcreate /dev/sd[b,c,d]1 : 创建三个物理卷
  3. pvs 进行查看 : 要显示的物理卷列表。

mark

  1. 建立卷组 :vgcreate 卷组名 要加入卷组的设备
    • vgcreate vg1 /dev/sdb1 /dev/sdc1
    • 注意 : 一个PV 是不能加到两个不同的卷组的

mark

  1. 查看卷组vgs
    • centos :pv = 1 说明物理卷有一个
    • centos : 中间有一个卷组
    • centos : lv = 2 说明逻辑卷有两个(/boot /

mark

  1. 创建逻辑卷
    • lvcreate -L 100M -n lv1 卷组名字
      • -L : 指定逻辑卷的大小
      • -n : 指定逻辑卷的名字

mark

2. 使用逻辑卷

  1. 格式化
    • mkfs.xfs /dev/vg1/lv1
  2. 进行挂载
    • mkdir
    • mount

逻辑卷的整个流程 : 分层结构

1
2
3
4
5
6
fdisk进行分区->物理卷pv->卷组vg->逻辑卷lv->文件系统xfs->挂载mount

逻辑卷功能 : 动态增大磁盘大小
最主要步骤 : 物理卷pv->卷组vg->逻辑卷lv

再加个RAID : fdisk进行分区->/dev/md0->物理卷pv->卷组vg->逻辑卷lv->文件系统xfs->挂载mount

3. 扩展分区 (lvm)

  • 扩展现有的分区
    • 根目录
    • boot目录

mark

概括:

  • vg空间不够,需先扩展vg,扩展vg就是往vg中加pv
    1. 新建pv,
    1. 进行扩容(vg),
    1. 再查看
    2. 进行扩容(lv)
  1. 给 vg 扩充空间

    • pvcreate /dev/sdd1 : 新建pv

    • vgextend centos /dev/sdd1vgextend 扩充谁 用谁扩充

    • pvs

    • lvs

    • vgs

mark

  1. lv 扩充空间
  • lvextend -L +50G /dev/centos/root : 给root逻辑卷增加50G的逻辑卷
  • pvs
  • lvs
  • vgs
  • 注意 : 给lv加的容量要小于vg的容量

mark

注意 : 空间真的变大了吗?

  • df -h : 查看发现一件奇怪的事情
    • 原因:逻辑卷上一层还有文件系统,文件系统还未进行扩大
    • 层次结构 : 物理卷 -》 逻辑卷-》文件系统
      • 不同分层解决不同的问题

mark

  • 解决方法
  • xfs_growfs /dev/centos/root : 告诉文件系统已经扩大了(xfs系统)

  • 缩容 : 不建议使用

1:umount 文件系统

2:缩减文件系统

此处参考博客: https://blog.csdn.net/qq_27281257/article/details/81603410

8.8 系统检查故障问题

mark

sar 命令安装 : yum install sysstat

1. sar

  1. cpu 利用率
  • sar -p(查看全天)

  • sar -u 1 10(1:每隔一秒,10:写入10次)

mark

CPU输出项说明

输出项 详细说明
CPU all 表示统计信息为所有 CPU 的平均值。
%user 显示在用户级别(application)运行使用 CPU 总时间的百分比。
%nice 显示在用户级别,用于nice操作,所占用 CPU 总时间的百分比。
%system 在核心级别(kernel)运行所使用 CPU 总时间的百分比。
%iowait 显示用于等待I/O操作占用 CPU 总时间的百分比。
%steal 管理程序(hypervisor)为另一个虚拟进程提供服务而等待虚拟 CPU 的百分比。
%idle 显示 CPU 空闲时间占用 CPU 总时间的百分比。
  1. 内存情况
  • sar -r (查看全天)

  • sar -r 1 10 (1:每隔一秒,10:写入10次)

mark

输出项 详细说明
kbmemfree 这个值和free命令中的free值基本一致,所以它不包括buffer和cache的空间。
kbmemused 这个值和free命令中的used值基本一致,所以它包括buffer和cache的空间。
%memused 这个值是kbmemused和内存总量(不包括swap)的一个百分比。
kbbuffers和kbcached 这两个值就是free命令中的buffer和cache。
kbcommit 保证当前系统所需要的内存,即为了确保不溢出而需要的内存(RAM+swap)。
%commit 这个值是kbcommit与内存总量(包括swap)的一个百分比。
  1. 磁盘IO情况
  • sar -d(查看全天)

  • sar -d 1 2(1:每隔一秒,2:写入2次)

mark

输出项 详细说明
await 表示平均每次设备I/O操作的等待时间(以毫秒为单位)。
svctm 表示平均每次设备I/O操作的服务时间(以毫秒为单位)。
%util 表示一秒中有百分之几的时间用于I/O操作。
  1. 进程的使用
  • sar -q

  • sar -q 1 10

  1. IO情况
  • sar -b
  • sar -b 1 10
  1. 网络流量
  • sar -n DEV(查看全天)

  • sar -n DEV 1 2(1:每隔一秒,2:写入2次)

mark

输出项 详细说明
IFACE 就是网络设备的名称。
rxpck/s 每秒钟接收到的包数目。
txpck/s 每秒钟发送出去的包数目。
rxkB/s 每秒钟接收到的字节数。
txkB/s 每秒钟发送出去的字节数。
rxcmp/s 每秒钟接收到的压缩包数目。
txcmp/s 每秒钟发送出去的压缩包数目。
rxmcst/s 每秒钟接收到的多播包的包数目。

2. iftop

  • 查看本地网络流量情况

  • iftop -P

mark

9. shell

mark

9.1 什么是shell?

mark

  • Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。
  • Shell 既是一种命令语言,又是一种程序设计语言。
  • Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
  • Ken Thompson 的 sh 是第一种 Unix Shell,Windows Explorer 是一个典型的图形界面 Shell。

在线工具Shell 在线工具

命令解释器

  • Shell 编程跟JavaScript、php 编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。
  • LinuxShell 种类众多,常见的有:
1
2
3
4
5
6
7
8
9
10
11
12
13
[root@zhuuu ~]# cat /etc/shells 
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh

本教程关注的是 Bash,也就是 Bourne Again Shell,由于易用和免费,Bash 在日常工作中被广泛使用。同时,Bash 也是大多数Linux 系统默认的 Shell。

在一般情况下,人们并不区分 Bourne Shell 和 Bourne Again Shell,所以,像 #!/bin/sh,它同样也可以改为 #!/bin/bash。

#! 告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序。

9.2 Linux 启动过程

mark

上述图为centos7,下面文字为centos6.

linux启动时我们会看到许多启动信息。

Linux系统的启动过程并不是大家想象中的那么复杂,其过程可以分为5个阶段:

  • 内核的引导。
  • 运行 init。
  • 系统初始化。
  • 建立终端 。
  • 用户登录系统。

init程序的类型:

  • SysV: init, CentOS 5之前, 配置文件: /etc/inittab。
  • Upstart: init,CentOS 6, 配置文件: /etc/inittab, /etc/init/*.conf。
  • Systemd: systemd, CentOS 7,配置文件: /usr/lib/systemd/system、 /etc/systemd/system。

1. 内核引导

  • 当计算机打开电源后,首先是BIOS开机自检,按照BIOS中设置的启动设备(通常是硬盘)来启动。
  • 操作系统接管硬件以后,首先读入 /boot 目录下的内核文件。

mark

2. 运行init(1号进程)

  • init 进程是系统所有进程的起点,你可以把它比拟成系统所有进程的老祖宗,没有这个进程,系统中任何进程都不会启动。

  • init 程序首先是需要读取配置文件 /etc/inittab

mark

3. 运行级别

  • 许多程序需要开机启动。它们在Windows叫做”服务”(service),在Linux就叫做”守护进程”(daemon)。

  • init进程的一大任务,就是去运行这些开机启动的程序。

    • 但是,不同的场合需要启动不同的程序,比如用作服务器时,需要启动Apache,用作桌面就不需要。
  • Linux允许为不同的场合,分配不同的开机启动程序,这就叫做”运行级别”(runlevel)。也就是说,启动时根据”运行级别”,确定要运行哪些程序。

mark

Linux系统有7个运行级别(runlevel):

  • 运行级别0:系统停机状态,系统默认运行级别不能设为0,否则不能正常启动
  • 运行级别1:单用户工作状态,root权限,用于系统维护,禁止远程登陆
  • 运行级别2:多用户状态(没有NFS)
  • 运行级别3:完全的多用户状态(有NFS),登陆后进入控制台命令行模式
  • 运行级别4:系统未使用,保留
  • 运行级别5:X11控制台,登陆后进入图形GUI模式
  • 运行级别6:系统正常关闭并重启,默认运行级别不能设为6,否则不能正常启动

4. 系统初始化

mark

  • 在init的配置文件中有这么一行: si::sysinit:/etc/rc.d/rc.sysinit 它调用执行了/etc/rc.d/rc.sysinit,而rc.sysinit是一个bash shell的脚本,它主要是完成一些系统初始化的工作,rc.sysinit是每一个运行级别都要首先运行的重要脚本。

  • 它主要完成的工作有:激活交换分区,检查磁盘,加载硬件模块以及其它一些需要优先执行任务。

1
l5:5:wait:/etc/rc.d/rc 5
  • 这一行表示以5为参数运行/etc/rc.d/rc/etc/rc.d/rc是一个Shell脚本,它接受5作为参数,去执行/etc/rc.d/rc5.d/目录下的所有的rc启动脚本,/etc/rc.d/rc5.d/目录中的这些启动脚本实际上都是一些连接文件,而不是真正的rc启动脚本,真正的rc启动脚本实际上都是放在/etc/rc.d/init.d/目录下。

  • 而这些rc启动脚本有着类似的用法,它们一般能接受start、stop、restart、status等参数。

5. 建立终端

  • rc执行完毕后,返回init。这时基本系统环境已经设置好了,各种守护进程也已经启动了。
  • init接下来会打开6个终端,以便用户登录系统。在inittab中的以下6行就是定义了6个终端:
1
2
3
4
5
6
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
  • 从上面可以看出在2、3、4、5的运行级别中都将以respawn方式运行mingetty程序,mingetty程序能打开终端、设置模式。
  • 同时它会显示一个文本登录界面,这个界面就是我们经常看到的登录界面,在这个登录界面中会提示用户输入用户名,而用户输入的用户将作为参数传给login程序来验证用户的身份。

6. 用户登录系统

一般来说,用户的登录方式有三种:

  • (1)命令行登录
  • (2)ssh登录
  • (3)图形界面登录

mark

图形方式登录

对于运行级别为5的图形方式用户来说,他们的登录是通过一个图形化的登录界面。登录成功后可以直接进入 KDE、Gnome 等窗口管理器。

而本文主要讲的还是文本方式登录的情况:当我们看到mingetty的登录界面时,我们就可以输入用户名和密码来登录系统了。

文字模式登录

  • Linux 的账号验证程序是loginlogin会接收 mingetty传来的用户名作为用户名参数。
  • 然后 login会对用户名进行分析:如果用户名不是 root,且存在/etc/nologin 文件,login 将输出nologin 文件的内容,然后退出。
  • 这通常用来系统维护时防止非root用户登录。只有/etc/securetty中登记了的终端才允许 root 用户登录
    • 如果不存在这个文件,则 root 用户可以在任何终端上登录。
    • /etc/usertty文件用于对用户作出附加访问限制,如果不存在这个文件,则没有其他限制。

5. 图形模式和文字模式切换

  • Linux预设提供了六个命令窗口终端机让我们来登录。

  • 默认我们登录的就是第一个窗口,也就是tty1,这个六个窗口分别为tty1,tty2 … tty6,你可以按下Ctrl + Alt + F1 ~ F6 来切换它们

  • 如果你安装了图形界面,默认情况下是进入图形界面的,此时你就可以按Ctrl + Alt + F1 ~ F6来进入其中一个命令窗口界面。

  • 当你进入命令窗口界面后再返回图形界面只要按下Ctrl + Alt + F7 就回来了。

  • 如果你用的vmware 虚拟机,命令窗口切换的快捷键为 Alt + Space + F1F6. 如果你在图形界面下请按Alt + Shift + Ctrl + F1F6 切换至命令窗口。

mark

7. linux 关机

在linux领域内大多用在服务器上,很少遇到关机的操作。毕竟服务器上跑一个服务是永无止境的,除非特殊情况下,不得已才会关机。

正确的关机流程为:sync > shutdown > reboot > halt

关机指令为:shutdown ,你可以man shutdown 来看一下帮助文档。

例如你可以运行如下命令关机:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
sync 将数据由内存同步到硬盘中。

shutdown 关机指令,你可以man shutdown 来看一下帮助文档。例如你可以运行如下命令关机:

shutdown –h 10 ‘This server will shutdown after 10 mins’ 这个命令告诉大家,计算机将在10分钟后关机,并且会显示在登陆用户的当前屏幕中。

shutdown –h now 立马关机

shutdown –h 20:25 系统会在今天20:25关机

shutdown –h +10 十分钟后关机

shutdown –r now 系统立马重启

shutdown –r +10 系统十分钟后重启

reboot 就是重启,等同于 shutdown –r now

halt 关闭系统,等同于shutdown –h now 和 poweroff
  • 最后总结一下,不管是重启系统还是关闭系统,首先要运行 sync 命令,把内存中的数据写到磁盘中。

  • 关机的命令有 shutdown –h now /halt/ poweroffinit 0 , 重启系统的命令有 shutdown –r now /reboot/ init 6

9.3 启动文件位置

1. MBR 位置

  1. 将MBR的引导写出来(446字节) : dd if=/dev/vda of=mbr.bin bs=446 count=1
  2. 16进制字符查看mbr : hexdump -C mbr.bin
  3. 将MBR的引导写出来(512字节) : dd if=/dev/vda of=mbr.bin bs=512 count=1
    • 512字节包含磁盘的分区表
    • 55 aa : 说明该磁盘可以正确引导
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
[root@zhuuu ~]# dd if=/dev/vda of=mbr.bin bs=446 count=1
1+0 records in
1+0 records out
446 bytes (446 B) copied, 0.000123157 s, 3.6 MB/s
[root@zhuuu ~]# hexdump -C mbr.bin
00000000 eb 63 90 10 8e d0 bc 00 b0 b8 00 00 8e d8 8e c0 |.c..............|
00000010 fb be 00 7c bf 00 06 b9 00 02 f3 a4 ea 21 06 00 |...|.........!..|
00000020 00 be be 07 38 04 75 0b 83 c6 10 81 fe fe 07 75 |....8.u........u|
00000030 f3 eb 16 b4 02 b0 01 bb 00 7c b2 80 8a 74 01 8b |.........|...t..|
00000040 4c 02 cd 13 ea 00 7c 00 00 eb fe 00 00 00 00 00 |L.....|.........|
00000050 00 00 00 00 00 00 00 00 00 00 00 80 01 00 00 00 |................|
00000060 00 00 00 00 ff fa 90 90 f6 c2 80 74 05 f6 c2 70 |...........t...p|
00000070 74 02 b2 80 ea 79 7c 00 00 31 c0 8e d8 8e d0 bc |t....y|..1......|
00000080 00 20 fb a0 64 7c 3c ff 74 02 88 c2 52 be 05 7c |. ..d|<.t...R..||
00000090 b4 41 bb aa 55 cd 13 5a 52 72 3d 81 fb 55 aa 75 |.A..U..ZRr=..U.u|
000000a0 37 83 e1 01 74 32 31 c0 89 44 04 40 88 44 ff 89 |7...t21..D.@.D..|
000000b0 44 02 c7 04 10 00 66 8b 1e 5c 7c 66 89 5c 08 66 |D.....f..\|f.\.f|
000000c0 8b 1e 60 7c 66 89 5c 0c c7 44 06 00 70 b4 42 cd |..`|f.\..D..p.B.|
000000d0 13 72 05 bb 00 70 eb 76 b4 08 cd 13 73 0d 5a 84 |.r...p.v....s.Z.|
000000e0 d2 0f 83 de 00 be 85 7d e9 82 00 66 0f b6 c6 88 |.......}...f....|
000000f0 64 ff 40 66 89 44 04 0f b6 d1 c1 e2 02 88 e8 88 |d.@f.D..........|
00000100 f4 40 89 44 08 0f b6 c2 c0 e8 02 66 89 04 66 a1 |.@.D.......f..f.|
00000110 60 7c 66 09 c0 75 4e 66 a1 5c 7c 66 31 d2 66 f7 |`|f..uNf.\|f1.f.|
00000120 34 88 d1 31 d2 66 f7 74 04 3b 44 08 7d 37 fe c1 |4..1.f.t.;D.}7..|
00000130 88 c5 30 c0 c1 e8 02 08 c1 88 d0 5a 88 c6 bb 00 |..0........Z....|
00000140 70 8e c3 31 db b8 01 02 cd 13 72 1e 8c c3 60 1e |p..1......r...`.|
00000150 b9 00 01 8e db 31 f6 bf 00 80 8e c6 fc f3 a5 1f |.....1..........|
00000160 61 ff 26 5a 7c be 80 7d eb 03 be 8f 7d e8 34 00 |a.&Z|..}....}.4.|
00000170 be 94 7d e8 2e 00 cd 18 eb fe 47 52 55 42 20 00 |..}.......GRUB .|
00000180 47 65 6f 6d 00 48 61 72 64 20 44 69 73 6b 00 52 |Geom.Hard Disk.R|
00000190 65 61 64 00 20 45 72 72 6f 72 0d 0a 00 bb 01 00 |ead. Error......|
000001a0 b4 0e cd 10 ac 3c 00 75 f4 c3 00 00 00 00 00 00 |.....<.u........|
000001b0 00 00 00 00 00 00 00 00 89 ac 09 00 00 00 |..............|
000001be
  • 512 字节
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[root@zhuuu ~]# dd if=/dev/vda of=mbr2.bin bs=512 count=1
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000130971 s, 3.9 MB/s
[root@zhuuu ~]# hexdump -C mbr2.bin
00000000 eb 63 90 10 8e d0 bc 00 b0 b8 00 00 8e d8 8e c0 |.c..............|
00000010 fb be 00 7c bf 00 06 b9 00 02 f3 a4 ea 21 06 00 |...|.........!..|
00000020 00 be be 07 38 04 75 0b 83 c6 10 81 fe fe 07 75 |....8.u........u|
00000030 f3 eb 16 b4 02 b0 01 bb 00 7c b2 80 8a 74 01 8b |.........|...t..|
00000040 4c 02 cd 13 ea 00 7c 00 00 eb fe 00 00 00 00 00 |L.....|.........|
00000050 00 00 00 00 00 00 00 00 00 00 00 80 01 00 00 00 |................|
00000060 00 00 00 00 ff fa 90 90 f6 c2 80 74 05 f6 c2 70 |...........t...p|
00000070 74 02 b2 80 ea 79 7c 00 00 31 c0 8e d8 8e d0 bc |t....y|..1......|
00000080 00 20 fb a0 64 7c 3c ff 74 02 88 c2 52 be 05 7c |. ..d|<.t...R..||
00000090 b4 41 bb aa 55 cd 13 5a 52 72 3d 81 fb 55 aa 75 |.A..U..ZRr=..U.u|
000000a0 37 83 e1 01 74 32 31 c0 89 44 04 40 88 44 ff 89 |7...t21..D.@.D..|
000000b0 44 02 c7 04 10 00 66 8b 1e 5c 7c 66 89 5c 08 66 |D.....f..\|f.\.f|
000000c0 8b 1e 60 7c 66 89 5c 0c c7 44 06 00 70 b4 42 cd |..`|f.\..D..p.B.|
000000d0 13 72 05 bb 00 70 eb 76 b4 08 cd 13 73 0d 5a 84 |.r...p.v....s.Z.|
000000e0 d2 0f 83 de 00 be 85 7d e9 82 00 66 0f b6 c6 88 |.......}...f....|
000000f0 64 ff 40 66 89 44 04 0f b6 d1 c1 e2 02 88 e8 88 |d.@f.D..........|
00000100 f4 40 89 44 08 0f b6 c2 c0 e8 02 66 89 04 66 a1 |.@.D.......f..f.|
00000110 60 7c 66 09 c0 75 4e 66 a1 5c 7c 66 31 d2 66 f7 |`|f..uNf.\|f1.f.|
00000120 34 88 d1 31 d2 66 f7 74 04 3b 44 08 7d 37 fe c1 |4..1.f.t.;D.}7..|
00000130 88 c5 30 c0 c1 e8 02 08 c1 88 d0 5a 88 c6 bb 00 |..0........Z....|
00000140 70 8e c3 31 db b8 01 02 cd 13 72 1e 8c c3 60 1e |p..1......r...`.|
00000150 b9 00 01 8e db 31 f6 bf 00 80 8e c6 fc f3 a5 1f |.....1..........|
00000160 61 ff 26 5a 7c be 80 7d eb 03 be 8f 7d e8 34 00 |a.&Z|..}....}.4.|
00000170 be 94 7d e8 2e 00 cd 18 eb fe 47 52 55 42 20 00 |..}.......GRUB .|
00000180 47 65 6f 6d 00 48 61 72 64 20 44 69 73 6b 00 52 |Geom.Hard Disk.R|
00000190 65 61 64 00 20 45 72 72 6f 72 0d 0a 00 bb 01 00 |ead. Error......|
000001a0 b4 0e cd 10 ac 3c 00 75 f4 c3 00 00 00 00 00 00 |.....<.u........|
000001b0 00 00 00 00 00 00 00 00 89 ac 09 00 00 00 80 00 |................|
000001c0 21 02 83 0f ff ff 00 08 00 00 df f7 3f 06 00 00 |!...........?...|
000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
00000200

2. grub2 位置

  • 位置 : cd /boot/grub2

  • 目前引导内核 : grub2-editenv list

    • 或者 : uname -r

3. init/systemd 区别

  • 一号进程
    • init : [root@zhuuu ~]# which init /usr/sbin/init
    • systemd:/usr/lib/systemd/systemd
  1. init
  • 系统脚本位置 : cd /etc/rc.d
  1. systemd
  • 系统配置文件位置 :cd /etc/systemd/system

注意

  • init 用的是脚本 , systemd 目录存放的多是配置文件
  • centos 6 和 centos 7的区别

9.4 shell 脚本

mark

  • Shell 脚本(shell script),是一种为 shell 编写的脚本程序。

  • 业界所说的 shell 通常都是指 shell 脚本,但读者朋友要知道,shell 和 shell script 是两个不同的概念。

1. 第一个脚本程序

mark

  • 实现功能 : 进入一个目录并查看目录下的内容
1
cd /var/;ls;pwd;du -sh *;du -sh
  1. vim 1.sh
1
2
3
4
5
cd /var/
ls
pwd
du -sh *
du -sh
  1. 加上执行权限chmod u+x 1.sh

  2. 运行脚本bash 1.sh

    • 使用bash shell 来执行

注意:

  • 如果对方默认的shell 不是 bash的话,需要在顶格加上声明
1
2
3
4
5
6
1 #!/bin/bash
2 cd /var/
3 ls
4 pwd
5 du -sh *
6 du -sh
  • ./1.sh : 会用系统自带的shell 进行执行
    • 如果有注释,使用注释的shell进行执行
  • 注释使用 # :注意顶格写
  • 需要注意的是:执行结果告知
    • $? : 可以来标识一个命令执行的成功与否
    • 还可以使用exit n 来自定义程序的中断退出,返回一个数值给系统
      • 如:exit 0 ,执行完毕脚本后,在执行echo $? 就可以拿到0的值

mark

2. 脚本的启动方式

mark

  1. bash./filename.sh会再新开一个bash子进程去执行
  2. source ./filename.sh.filename.sh会使用当前的进程去执行

举例子 : 编写一个2.sh脚本

1
2
cd /tmp
pwd
  1. bash 2.sh
    • 虽然没有赋予权限,但是执行完脚本,又回到了当前目录
  2. ./2.sh
    • 会提示权限不够,必须添加chmod u+x 2.sh
    • 执行完脚本,又回到了当前目录

以上两种方式因为是新的子进程,所以执行完对当前的环境是没有影响的


  1. source ./2.sh
    • 当前的目录受到更改
  2. . 2.sh
    • 和 source 其实是同一个命令,当前目录受到更改

注意 :

  • 如果想要脚本对当前的bash产生影响,使用source ./ 或者 .sh
  • 否则使用./ sh 方式去运行

内建命令和外部命令的区别

  1. 上述cd 和pwd 命令属于内建命令,对当前的bash 会产生影响(因为不会产生子进程)
  2. 可以使用type command 来查询是否是内部命令
    • 如:type cd : cd is a shell builtin

mark

9.5 管道和重定向

mark

1. 管道

mark

  • 将多个进程的输入和输出连在一起
  • 管道符 : |
    • 代表的是匿名管道
    • 管道的原因:bash 执行命令会产生数据,这些数据必须通过几道处理之后才能达到我们想要的输出

举个例子

  1. # 将前面cat的结果当做 | 后more的输入
    # 这里实际和more+文件是一个效果
    
    cat /etc/dracut.conf | more
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29

    2. `cat | ps -f`

    ![mark](http://zhuuu-bucket.oss-cn-beijing.aliyuncs.com/img/20210107/104957287.png)

    - **cat 和 ps 都是外部命令**
    - bash 开了**两个子进程**来进行外部命令的程序
    - `20502` 和 `20503` 是子进程
    - 如下图所示
    - **cat 输出** :到管道 172657的管道
    - **ps 的输入** :就是管道 即172657的管道

    ![mark](http://zhuuu-bucket.oss-cn-beijing.aliyuncs.com/img/20210107/105316851.png)



    **注意 : 两个概念问题**

    1. **子shell**
    - 子进程是`shell `的话就叫做子shell
    - 管道符是可以创建子进程的

    2. **管道符如果使用内部命令**
    - 作用范围只在那个脚本里面生效
    - **避免在管道符中使用内部命令**

    ```sh
    [root@zhuuu /]# cd /etc/ | pwd
    /

2. 重定向

  • 大多数UNIX系统命令从你的终端接受输入并将所产生的输出发送回到您的终端。
  • 一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端。同样,一个命令通常将其输出写入到标准输出,默认情况下,这也是你的终端。
  • 本质 : 利用文件代替终端进行输出/输入
1
2
3
4
需要注意的是文件描述符 fd
0 通常是标准输入(STDIN),
1 是标准输出(STDOUT),
2 是标准错误输出(STDERR)。

重定向符号

mark

命令 说明
command > file 将输出重定向到 file。
command < file 将输入重定向到 file。(会覆盖)
command >> file 将输出以追加的方式重定向到 file。(追加)
command 2> file 将输出的错误重定向到文件file当中。
command &> file 将无论什么内容都重定向输入到文件flie中
n > file 将文件描述符为 n 的文件重定向到 file。
n >> file 将文件描述符为 n 的文件以追加的方式重定向到 file。
n >& m 将输出文件 m 和 n 合并。
n <& m 将输入文件 m 和 n 合并。
<< tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入。
  1. 输入重定向
  • 和输出重定向一样,Unix 命令也可以从文件获取输入,语法为:
1
command1 < file1
  • 这样,本来需要从键盘获取输入的命令会转移到文件读取内容。

  • 注意:输出重定向是大于号(>),输入重定向是小于号(<)

举个例子

  • 输出/etc/passwd 文件的行数
1
wc -l < /etc/passwd
  1. 输出重定向
  • 重定向一般通过在命令间插入特定的符号来实现。特别的,这些符号的语法如下所示:
1
command1 > file1
  • 上面这个命令执行command1然后将输出的内容存入file1

  • 注意任何file1内的已经存在的内容将被新内容替代。

  • 如果要将新内容添加在文件末尾,请使用>>操作符。

举个例子

  • 输出123 到文件a.txt
1
echo 123 > a.txt
  • 输出错误信息重定向到文件
1
nocmd 2> c.txt
  • 无论正确还是错误 全部重定向到文件当中
1
nocmd &> c.txt

注意:

  • 如何将输出重定向的 正确信息和错误信息分开
    • command xxx > list_right 2 > list_error
    • 正确信息写入 :list_right
    • 错误信息写入 :list_error
  • 无论正确还是错误 全部重定向到文件当中
    • nocmd &> c.txt
  1. 输入输出重定向组合
    • 一般用于配置文件生成
    • 也就是 Here Document
  • Here Document是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。

  • 它的基本的形式如下:

1
2
3
command << delimiter(eof)
document
delimiter(eof)
  • 它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。

注意:

  • 结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。
  • 开始的delimiter前后的空格会被忽略掉。

举个例子

  • 通过一个脚本文件生成另外一个脚本文件
1
2
3
4
5
vim 3.sh
#!/bin/bash
cat > /root/a.sh <<EOF #将cat的内容写入/root/a.sh 以EOF结尾
echo "hello bash" #这里的内容都是写入到a.sh的内容
EOF #结束输入
  • 在命令行中通过 wc -l 命令计算 Here Document 的行数:

    1
    2
    3
    4
    5
    6
    7
    $ wc -l << EOF
    欢迎来到
    菜鸟教程
    www.runoob.com
    EOF
    3 # 输出结果为 3 行
    $

此处参考教程 : https://www.runoob.com/linux/linux-shell-io-redirections.html

9.6 变量

mark

1. 变量的定义和赋值

变量的定义

mark

注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。同时,变量名的命名须遵循如下规则:

  • 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
  • 中间不能有空格,可以使用下划线(_)。
  • 不能使用标点符号。
  • 不能使用bash里的关键字(可用help命令查看保留关键字)。
  1. 有效的 Shell 变量名示例如下:
1
2
3
4
RUNOOB
LD_LIBRARY_PATH
_var
var2
  1. 无效的变量命名:
1
2
?var=123
user*name=runoob

变量的赋值

mark

  • lect=$(ls -l /etc)

    • ls -l /etc 执行命令的结果赋值给lect这个变量
    • 这样的好处是避免每次执行命令的开销
    • 或者使用ls -ls/etc
  • 带空格的变量需要用 “ “ 或者 ‘ ‘包含

    • [root@zhuuu ~]# string1="hello bash"
      [root@zhuuu ~]# echo $string1
      hello bash
      
      1
      2
      3
      4
      5

      - ```sh
      [root@zhuuu ~]# string2='hello "bash"'
      [root@zhuuu ~]# echo $string2
      hello "bash"

变量的重新定义

  • 已定义的变量,可以被重新定义,如:
1
2
3
4
your_name="tom"
echo $your_name
your_name="alibaba"
echo $your_name
  • 这样写是合法的,但注意,第二次赋值的时候不能写$your_name="alibaba",使用变量的时候才加美元符($)。

2. 变量的引用

mark

  • 使用一个定义过的变量,只要在变量名前面加美元符号即可,如:
1
2
3
your_name="zhuuu"
echo $your_name
echo ${your_name}
  • 花括号的使用

    • 变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:

    • for skill in Ada Coffe Action Java; do
          echo "I am good at ${skill}Script"
      done
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36

      - 如果不给skill变量加花括号,写成`echo "I am good at $skillScript"`,解释器就会把`$skillScript`当成一个变量(其值为空),代码执行结果就不是我们期望的样子了。

      - **推荐给所有变量加上花括号,这是个好的编程习惯。**



      #### 3. 变量的作用范围

      ![mark](http://zhuuu-bucket.oss-cn-beijing.aliyuncs.com/img/20210107/150154856.png)

      运行shell时,会同时存在三种变量(默认是局部变量):

      - **1) 局部变量** : 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
      - **2) 环境变量** : 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
      - **3) shell变量** : shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行



      **注意:**

      1. **变量默认的作用范围**
      - 只对当前shell 有效
      - 子进程bash获取不到父进程变量
      - 父进程获取不到子进程变量

      **举个例子**

      - **子进程bash 获取不到父进程变量**

      ```sh
      [root@zhuuu ~]# a=1
      [root@zhuuu ~]# bash
      [root@zhuuu ~]# echo $a

      [root@zhuuu ~]#
  • 父进程获取不到子进程的变量

1
2
3
4
5
[root@zhuuu ~]# a=2
[root@zhuuu ~]# exit
exit
[root@zhuuu ~]# echo $a
1
  • 打开别的平行终端,变量也不会生效
  1. 改变变量的默认作用范围
  • 如运行: bash xx.sh
    • 那么 xx.sh 中的变量是属于子进程的 不会对当前生效的
    • 若想生效,xx.sh的启动应该改为 source xx.sh 或者 . sh

mark

  • 让子进程获取到父进程的变量
    • export 变量名 后再使用
    • 如下所示

mark

  1. 变量的删除
  • 使用 unset 命令可以删除变量。语法:
1
unset variable_name
  • 变量被删除后不能再次使用。unset 命令不能删除只读变量。

举个例子

1
2
3
4
#!/bin/sh
myUrl="https://www.runoob.com"
unset myUrl
echo $myUrl
  • 以上实例执行将没有任何输出。

4. 系统的环境变量

  • 让每一个进程都能读取到变量的值
  • 对于新的终端无效
  • 对于当前终端和子shell 有效

mark

  • 系统环境变量env | more
    • 默认都是大写的字母
  • 查看当前变量
1
2
3
4
[root@zhuuu ~]# echo $USER
root
[root@zhuuu ~]# echo $UID
0
  • 命令搜索路线 :

    • [root@zhuuu ~]# echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
  • 新增环境变量

    • PATH = PATH:/root : 新增root目录的环境变量
    • echo $PATH
    • 并且新增的环境变量 对于 任何路径都适用

5. 预定义变量

  • 常用的有
    • echo $? : 上一条命令是否正确执行
      • 0 表示上一条命令正确执行
      • 1 表示上一条命令错误执行
    • echo $0 :当前的进程名称
    • echo $$ : 显示当前进行的PID

mark

举个例子 : 同时打印PID 和 Pname

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@zhuuu ~]# PATH=$PATH:/root
[root@zhuuu ~]# vim 6.sh
[root@zhuuu ~]# 6.sh
-bash: /root/6.sh: Permission denied
[root@zhuuu ~]# chmod u+x 6.sh
[root@zhuuu ~]# vim 6.sh
[root@zhuuu ~]# 6.sh
23222
/root/6.sh


#6.sh
1 #!/bin/bash
2
3 # PID Pname
4 echo $$
5 echo $0


[root@zhuuu ~]# . 6.sh
20782
-bash

6. 位置变量

  • shell脚本添加更多的参数
  • 第 1 - 9 位置变量可以写 : $1-$9
  • 第10个位置变量要写为 : ${10}

脚本读取变量

  1. vim 7.sh
1
2
3
4
5
6
7
8
9
10
 1 #!/bin/bash
2
3 # $1 $2 ... $9 ${10}
4
5 pos1=$1
6 pos2=$2
7
8
9 echo $pos1
10 echo $pos2
  1. 读取到变量
1
2
3
4
5
6
7
8
[root@zhuuu ~]# vim 7.sh
[root@zhuuu ~]# chmod u+x 7.sh
[root@zhuuu ~]# . 7.sh


[root@zhuuu ~]# . 7.sh -a -l
-a
-l
  1. 7.sh 可以直接修改为
1
2
3
4
5
6
7
8
#!/bin/bash
echo $1
echo $2


[root@zhuuu ~]# . 7.sh -a -l
-a
-l

注意:

  • 规避读取的值是空值 : 使用下划线替代
1
2
echo $1
echo ${2}_
1
2
3
4
5
6
7
8
9
10
 1 #!/bin/bash
2
3 # $1 $2 ... $9 ${10}
4
5 pos1=$1
6 pos2=${2}_
7
8
9 echo $pos1
10 echo $pos2
  • *参数替换 *
    • 参数为空,赋值下划线
    • 参数有值,赋值传入的参数
1
2
3
4
5
6
7
8
9
10
 1 #!/bin/bash
2
3 # $1 $2 ... $9 ${10}
4
5 pos1=$1
6 pos2=${2-_}
7
8
9 echo $pos1
10 echo $pos2

7. 环境变量的配置文件

mark

  • 保存在/etc 中的所有用户都能够访问
  • 保存在 ~ 之后的是用户的家目录(保存用户特有的配置)
  • 永久添加环境变量 在上述任意配置文件添加即可
  1. /etc/profile

mark

  1. /etc/bashrc

mark

  1. .bashrc
  • 用户目录下的bashrc

mark

  1. .bash_profile
  • 用户目录下的bash_profile

mark

  1. 目录/etc/profile.d
1
2
3
4
[root@zhuuu ~]# ls /etc/profile.d/
256term.csh bash_completion.sh colorls.csh lang.csh less.sh vim.sh
256term.sh colorgrep.csh colorls.sh lang.sh sh.local which2.csh
abrt-console-notification.sh colorgrep.sh csh.local less.csh vim.csh which2.sh

注意:环境变量执行顺序问题

  • 配置文件是在每次打开终端的时候才会去运行

  • 定义环境变量可以在上述任意一个文件中定义

  • 当有重复的变量的时候,后面的变量会替换掉前面的变量

  • 使用loginshell 和 nologinshell 的区别

    • nologinshell 配置加载时不完全的
    • nologinshell配置环境与 正常登陆环境是不同的
    • su - 用户名loginshell
    • su 用户名 : nologinshell

mark

1
2
3
4
5
6
7
# 顺序
/etc/profile
.bash_profile
.bashrc
/etc/bashrc

export PATH=$PATH:/new/path 让自己进程和子进程都能够使用

mark

  • 新添加的环境变量是不会立即生效的

    • 添加生效的方法
      • 关掉终端重新打开
      • source 配置文件source /etc/bashrc
  • 建议使用su -用户名 登陆

9.7 数组

  • Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小(与 PHP 类似)
  • 与大部分编程语言类似,数组元素的下标由0开始。数组中可以存放多个值。
  • Shell 数组用括号来表示,元素用”空格”符号分割开

mark欧陆

语法格式如下:

1
array_name=(value1 value2 ... valuen)

定义数组

1
2
3
4
5
6
my_array=(A B "C" D)

#我们也可以使用下标来定义数组:
array_name[0]=value0
array_name[1]=value1
array_name[2]=value2
  1. 读取数组的元素
1
2
3
4
5
6
my_array=(A B "C" D)

echo "第一个元素为: ${my_array[0]}"
echo "第二个元素为: ${my_array[1]}"
echo "第三个元素为: ${my_array[2]}"
echo "第四个元素为: ${my_array[3]}"

执行脚本,输出结果如下所示:

1
2
3
4
5
6
$ chmod +x test.sh 
$ ./test.sh
第一个元素为: A
第二个元素为: B
第三个元素为: C
第四个元素为: D
  1. 获取数组中的所有元素
  • 使用@ 或 * 可以获取数组中的所有元素,例如:
1
2
3
4
5
6
7
my_array[0]=A
my_array[1]=B
my_array[2]=C
my_array[3]=D

echo "数组的元素为: ${my_array[*]}"
echo "数组的元素为: ${my_array[@]}"

执行脚本,输出结果如下所示:

1
2
3
4
$ chmod +x test.sh 
$ ./test.sh
数组的元素为: A B C D
数组的元素为: A B C D
  1. 获取数组的长度
1
2
3
4
5
6
7
8
9
- 获取数组长度的方法与获取字符串长度的方法相同,例如:

my_array[0]=A
my_array[1]=B
my_array[2]=C
my_array[3]=D

echo "数组元素个数为: ${#my_array[*]}"
echo "数组元素个数为: ${#my_array[@]}"

执行脚本,输出结果如下所示:

1
2
3
4
$ chmod +x test.sh 
$ ./test.sh
数组元素个数为: 4
数组元素个数为: 4

9.8 转义和引用

1. 特殊字符

mark

  • # : 注释
  • ; : 连接两条命令或者两个脚本
  • \ : 可以转义两类符号
    • 字母 : 转换成特殊的功能(如 : \n \r \t)
    • 非字母 :显示特殊字符(如\$ \" \\

mark

  1. 转义符号
1
2
3
4
5
6
7
8
9
[root@zhuuu ~]# echo "$a"

[root@zhuuu ~]# echo "\$a"
$a

[root@zhuuu ~]# echo " abc"x"edf "
abcxedf
[root@zhuuu ~]# echo " abc\"x\"edf "
abc"x"edf

2. 引用

"" 和 '' 对变量的影响

  • 双引号和单引号 对于变量的不同
    • 双引号 : 不完全引用
      • 如果里面是变量就引用变量的值
    • 单引号 : 完全引用
      • 里面是什么就显示什么的值
  • 反引号 : ` : 对于命令的引用

9.9 运算符

Shell 和其他编程语言一样,支持多种运算符,包括:

  • 算数运算符(只支持整数的运算)
  • 关系运算符
  • 布尔运算符
  • 字符串运算符
  • 文件测试运算符

1. 算术运算符

mark

注意 :

  • 原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。

  • expr 是一款表达式计算工具,使用它能完成表达式的求值操作。

  • expr 只支持整数,不支持小数和浮点数

mark

下表列出了常用的算术运算符,假定变量 a 为 10,变量 b 为 20:

运算符 说明 举例
+ 加法 expr $a + $b 结果为 30。
- 减法 expr $a - $b 结果为 -10。
* 乘法 expr $a \* $b 结果为 200。
/ 除法 expr $b / $a 结果为 2。
% 取余 expr $b % $a 结果为 0。
= 赋值 a=$b 将把变量 b 的值赋给 a。

例子1 :

1
2
3
4
#!/bin/bash

val=`expr 2 + 2`
echo "两数之和为 : $val"

执行脚本,输出结果如下所示:

1
两数之和为 : 4

两点注意:

  • 表达式和运算符之间要有空格,例如2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
  • 完整的表达式要被 `` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。
  • 例如,两个数相加 *注意使用的是反引号 ` 而不是单引号 ‘ *

2. 数字常量(整数运算)

mark

  • let 命令很少用
  • let 命令简化 : 双圆括号
1
2
3
4
5
自加操作:let no++

自减操作:let no--

简写形式 let no+=10,let no-=20,分别等同于 let no=no+10,let no=no-20。

mark

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 使用双圆括号
[root@zhuuu ~]# (( a=4+5 ))
[root@zhuuu ~]# echo $a
9

# 单独使用运算法 : 返回字符串的结果
[root@zhuuu ~]# b=4+5
[root@zhuuu ~]# echo $b
4+5

# ++ 功能 -- 功能
[root@zhuuu ~]# (( a++ ))
[root@zhuuu ~]# echo $a
10

3. 测试(test)

mark

  • shell 中 exit 作用
  1. 作用一 : 返回上面出错
1
2
3
4
5
6
7
8
9
10
11
12
13
[root@zhuuu ~]# vim 8.sh
[root@zhuuu ~]# bash 8.sh
8.sh: line 5: ppwd: command not found
[root@zhuuu ~]# echo $?
127

8.sh
1 #!/bin/bash
2
3 #exit demo
4
5 ppwd
6 exit
  1. 作用于 : 自定义错误返回值
1
2
3
4
5
6
7
8.sh
1 #!/bin/bash
2
3 #exit demo
4
5 pwd
6 exit 127

  • 测试命令 : test

mark

注意:

  • 在shell 中
    • 0 为 True
    • 1 为 False
  1. 字符串测试

mark

1
2
3
4
5
6
7
8
9
10
11
12
# 字符串比较是区分大小写的
[root@zhuuu ~]# [ "abc" = "ABC" ]
[root@zhuuu ~]# echo $?
1
[root@zhuuu ~]# [ "abc" = "abc" ]
[root@zhuuu ~]# echo $?
0

# 完整版如下
[root@zhuuu ~]# test "abc" = "ABC"
[root@zhuuu ~]# echo $?
1
  1. 整数测试

mark

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 判断 5 > 4?
[root@zhuuu ~]# [ 5 -gt 4 ]
[root@zhuuu ~]# echo $?
0
[root@zhuuu ~]# [ 5 > 4 ] 注意 : 这种写法是不对的 因为[]是不支持大于小于号的
[root@zhuuu ~]# echo $?
0
[root@zhuuu ~]# [[ 5 > 4 ]]
[root@zhuuu ~]# echo $?
0

# 常见的大小比较
-gt 大于
-lt 小于
-eq 相等
-ge 大于等于
-le 小于等于
  1. 文件测试

mark

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 判断文件是否存在
[root@zhuuu ~]# test -f /etc/passwd
[root@zhuuu ~]# echo $?
0
[root@zhuuu ~]# test -f /etc/passwd2
[root@zhuuu ~]# echo $?
1

# 使用括号写法
[root@zhuuu ~]# [ -d /etc/ ]
[root@zhuuu ~]# echo $?
0
[root@zhuuu ~]# [ -e /etc/ ]
[root@zhuuu ~]# echo $?
0

4. 特殊符号大全

mark

  1. 引号
    • 完全引用 : 单引号
    • 不完全引用:双引号
    • 执行命令 : 反引号
  1. 括号

mark

  • 圆括号() : 单独使用产生一个子shell
  • 方括号 [ ] : test命令
  • 尖括号 <> : 输入输出重定向
  • 花括号 {}: 输出范围

举例子:

  1. 圆括号

9.10 if 语句

mark

1. if 语句

  • if 语句语法格式:
1
2
3
4
5
6
7
if condition
then
command1
command2
...
commandN
fi

写成一行(适用于终端命令提示符):

1
if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi

末尾的fi就是if倒过来拼写,后面还会遇到类似的。

举个例子

  1. 判断当前用户是否是root
1
2
3
4
5
6
7
8
9
10
11
[root@zhuuu ~]# [ $UID = 0 ]
[root@zhuuu ~]# echo $?
0
[root@zhuuu ~]# [ $USER = root ]
[root@zhuuu ~]# echo $?
0
[root@zhuuu ~]# if [ $UID = 0 ]
> then
> echo "root user"
> fi
root user

2. if-else 语句

  • if else 语法格式:
1
2
3
4
5
6
7
8
9
if condition
then
command1
command2
...
commandN
else
command
fi

举个例子

  1. 判断当前用户是否是root
1
2
3
4
5
6
7
8
9
10
11
12
13
[user4@zhuuu ~]$ vim 9.sh
[user4@zhuuu ~]$ . 9.sh
otheruser

1 #!/bin/bash
2
3 #if-else
4
5 if [ $USER = root ] ;then
6 echo "rootuser"
7 else
8 echo "otheruser"
9 fi

3. if - elif - else 语句

mark

以下实例判断两个变量是否相等:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
a=10
b=20
if [ $a == $b ]
then
echo "a 等于 b"
elif [ $a -gt $b ]
then
echo "a 大于 b"
elif [ $a -lt $b ]
then
echo "a 小于 b"
else
echo "没有符合的条件"
fi

输出结果:

1
a 小于 b

注意 :

  • if else 语句经常与 test 命令结合使用,如下所示:
1
2
3
4
5
6
7
8
9
[user4@zhuuu /]$ num1=$[2*3]
[user4@zhuuu /]$ num2=$[1+5]
[user4@zhuuu /]$ if test $[num1] -eq $[num2]
> then
> echo "两个数字相等"
> else
> echo "两个数字不相等"
> fi
两个数字相等

4. 嵌套 if

mark

9.11 case 语句

  • 多分支if 使用 case 更加方便
  • Shell case语句为多选择语句。
  • 可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。

mark

  • case语句格式如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
casein
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac

举个例子

  • 实现一个可以同时控制脚本start stop restart 的 script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@zhuuu ~]# vim 12.sh
[root@zhuuu ~]# ./12.sh start
./12.sh start....

1 #!/bin/bash
2
3 # case demo
4
5 case "$1" in
6 "start"|"START")
7 echo $0 start....
8 ;;
9 "stop"|"STOP")
10 echo $0 stop...
11 ;;
12 "restart"|"RESTART")
13 echo $0 restart
14 ;;
15 *)
16 echo "Usage : $0 {start|stop|restart}"
17 ;;
18 esac
  • case工作方式如上所示。取值后面必须为单词in,每一模式必须以右括号结束。
  • 取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至;;
  • 取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。
  • 如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。

下面的脚本提示输入1到4,与每一种模式进行匹配:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
1) echo '你选择了 1'
;;
2) echo '你选择了 2'
;;
3) echo '你选择了 3'
;;
4) echo '你选择了 4'
;;
*) echo '你没有输入 1 到 4 之间的数字'
;;
esac

9.12 循环

mark

1. for 循环

mark

  • for循环一般格式为(python 风格):
1
2
3
4
5
6
7
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
  • 写成一行:
1
for var in item1 item2 ... itemN; do command1; command2… done;
  • 简单举例子 : 打印1-9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@zhuuu mail]# echo {1..9}
1 2 3 4 5 6 7 8 9 # 一次性输出
[root@zhuuu mail]# for i in {1..9}
> do
> echo $i
> done
# 一个一个输出
1
2
3
4
5
6
7
8
9

mark

  • 当变量值在列表里,for循环即执行一次所有命令,使用变量名获取列表中的当前取值。

  • 命令可为任何有效的shell命令和语句。in列表可以包含变量、字符串和文件名,花括号,文本。

  • 将多个相同文件进行批量改名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1. 取出文件名
[root@zhuuu ~]# touch a.mp3 b.mp3
[root@zhuuu ~]# basename a.mp3 .mp3
a

# 2. 进行改名
[root@zhuuu ~]# touch a.mp3 b.mp3
[root@zhuuu ~]# basename a.mp3 .mp3
a
[root@zhuuu ~]# for filename in `ls *.mp3`
> do
> mv $filename $(basename $filename .mp3).mp4
> done
[root@zhuuu ~]# ls *.mp4
a.mp4 b.mp4

注意 :

  • for i in {1..9 } : 逐个操作 i
  • 单纯的 mkdir {1..9} : 批量去操作

2. C 语言风格 (不常用)

mark

  • 简单例子:打印 1-10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@zhuuu ~]# for ((i=1;i<=10;i++))
> do
> echo $i
> done
1
2
3
4
5
6
7
8
9
10

3. while 循环

mark

  • while循环用于不断执行一系列命令,也用于从输入文件中读取数据;
  • 命令通常为测试条件。其格式为:
1
2
3
4
while condition
do
command
done

举个例子

  • 以下是一个基本的while循环,测试条件是:如果int小于等于5,那么条件返回真。
  • int从0开始,每次循环处理时,int加1。运行上述脚本,返回数字1到5,然后终止。
1
2
3
4
5
6
7
8
9
10
11
12
 1 #!/bin/bash
2
3 # while demo
4
5 int=1
6 while(( $int <= 5 ))
7 do
8 echo $int
9 let "int++" #(( a++ ))
10 done

# 以上实例使用了 Bash let 命令,它用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量
  • 利用while产生死循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
while :
do
cmd1
done

# 或者

while true
do
command
done

# 或者
for (( ; ; ))

4. until 循环

mark

  • 和 while 是相反的

    • 如果条件为假,循环一直执行
    • 如果条件为真,循环退出
  • until 循环执行一系列命令直至条件为 true 时停止。

  • 一般 while 循环优于 until 循环,但在某些时候—也只是极少数情况下,until 循环更加有用。

  • until 语法格式:

    • condition 一般为条件表达式,如果返回值为 false,则继续执行循环体内的语句,否则跳出循环。
1
2
3
4
until condition
do
command
done
  • 举个例子 : 以下实例我们使用 until 命令来输出 0 ~ 9 的数字
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  1 #!/bin/bash
2
3 #until demo
4
5 a=0
6
7 until [ ! $a -lt 10 ]
8 do
9 echo $a
10 a=` expr $a + 1` # (( a++ ))
11 done


[root@zhuuu ~]# . 14.sh
0
1
2
3
4
5
6
7
8
9

5. break / continue

mark

  1. break
  • break命令允许跳出所有循环(终止执行后面的所有循环)。

  • break 作用于:

    • 内层循环 : 内层循环结束
    • 外层循环 : 外层循环结束
  • 简单例子 : 打印终止

1
2
3
4
5
6
7
8
9
10
11
[root@zhuuu ~]# for num in {1..9}
> do
> if [ $num -eq 5 ]; then
> break
> fi
> echo $num
> done
1
2
3
4
  • 举个例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
下面的例子中,脚本进入死循环直至用户输入数字大于5。要跳出这个循环,返回到shell提示符下,需要使用break命令。

实例
#!/bin/bash
while :
do
echo -n "输入 1 到 5 之间的数字:"
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
break
;;
esac
done
  1. continue
  • continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。

  • 简单例子 : 打印跳过

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@zhuuu ~]
for num in {1..9}
do
if [ $num -eq 5 ]
then continue;
fi;
echo $num;
done
1
2
3
4
6
7
8
9
  • 死循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash
while :
do
echo -n "输入 1 到 5 之间的数字: "
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的!"
continue
echo "游戏结束"
;;
esac
done
运行代码发现,当输入大于5的数字时,该例中的循环不会结束,语句 echo "游戏结束" 永远不会被执行。

6. 使用循环处理命令行参数

mark

参数:

  1. 可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n
  2. n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……

例子1 :

  • 以下实例我们向脚本传递三个参数,并分别输出,其中 $0 为执行的文件名(包含文件路径):
1
2
3
4
5
6
7
#!/bin/bash

echo "Shell 传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";
  • 结果 : 为脚本设置可执行权限,并执行脚本,输出结果如下所示:
1
2
3
4
5
6
7
$ chmod +x test.sh 
$ ./test.sh 1 2 3
Shell 传递参数实例!
执行的文件名:./test.sh
第一个参数为:1
第二个参数为:2
第三个参数为:3

还有几个特殊字符用来处理参数:

参数处理 说明
$# 传递到脚本参数的个数
$* 以一个单字符串显示所有向脚本传递的参数 注 : 如”$*”用「”」括起来的情况、以”$1 $2 … $n”的形式输出所有参数。
$$ 脚本当前运行的进程ID
$! 后台运行的最后一个进程的ID
$@ 与$*相同,但是使用时加引号,并在引号中返回每个参数。
如”$@”用「”」括起来的情况、以”$1” “$2” … “$n” 的形式输出所有参数。
$- 显示Shell使用的当前选项,与set命令功能相同。
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

注意点 : $* 与 $@ 区别:

  • 相同点:都是引用所有参数。
  • 不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,
    • " * " 等价于 "1 2 3"(传递了一个参数),
    • "@"等价于 "1" "2" "3"(传递了三个参数)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash

echo "-- \$* 演示 ---"
for i in "$*"; do
echo $i
done

echo "-- \$@ 演示 ---"
for i in "$@"; do
echo $i
done

# 执行脚本,输出结果如下所示:
$ chmod +x test.sh
$ ./test.sh 1 2 3
-- $* 演示 ---
1 2 3
-- $@ 演示 ---
1
2
3

处理参数样例:

1. for 循环 处理脚本参数
1
2
3
4
5
6
7
8
9
10
 1 #!/bin/bash
2
3 #for demo
4
5 for pos in $*
6 do
7 if [ "$pos" = "help" ] ;then
8 echo $pos $pos
9 fi
10 done
2. while 循环 处理脚本参数
1
2
3
4
5
6
7
8
9
10
11
12
  1 #!/bin/bash
2
3 while [ $# -ge 1 ]
4 do
5 if [ "$1" = "help" ]
6 then echo $1 $1
7 fi
8 shift
9 done

# shift的作用是参数左移,删除第一个参数,使得后面的参数提前
`ls -lrt` : 如果多个参数的命令,底层使用的是`shift` 平移

10. 函数

mark

10.1 自定义函数

mark

  • linux shell 可以用户定义函数,然后在shell脚本中可以随便调用。
  • shell中函数的定义格式如下:
1
2
3
4
5
6
7
8
9
[ function ] funname ()

{

action;

[return int;]

}

说明:

  • 1、可以带function fun() 定义,也可以直接fun()定义,不带任何参数。
  • 2、参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255)

  • 简单使用 : 合并cdls命令
1
2
3
4
5
6
7
8
[root@zhuuu ~]# function cdls(){
> cd /var
> ls
> }
[root@zhuuu ~]# cdls
adm cache crash db empty games gopher kerberos lib local lock log mail nis opt preserve run spool tmp yp

#function 可以省略
  • return : 下面定义一个带有return语句的函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash

funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum$anotherNum !"
return $(($aNum+$anotherNum)) # return $(( aNum + anotherNum ))
}
funWithReturn
echo "输入的两个数字之和为 $? !"


#输出类似下面:
这个函数会对输入的两个数字进行相加运算...
输入第一个数字:
1
输入第二个数字:
2
两个数字分别为 1 和 2 !
输入的两个数字之和为 3 !

10.2 自定义函数带参数

mark

  • 在Shell中,调用函数时可以向其传递参数。

  • 在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数…

  • 简单例子 : 合并cd 和 ls

1
2
3
4
5
6
[root@zhuuu var]# cdls(){
> cd $1
> ls
> }

[root@zhuuu var]# cdls /tmp

10.3 局部变量

  • 函数内部的变量使用 : local
  • 作用 : 防止和函数外部变量重名
  • 举个例子 : 检查后台进程
    • 有 :返回0
    • 没有 :返回1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 1 #!/bin/bash
2
3 #funtions
4
5 checkPID(){
6 # i 只在本地有效,防止外部i影响函数内部
7 local i
8 # 遍历所有参数
9 for i in $*;
10 # 检查是否有对应进程号的proc目录
11 do
12 [ -d "proc/$i" ] && return 0 # 有返回0
13 done
14 return 1 # 没有返回1
15 }

10.4 系统函数库

mark

  1. 查看系统函数库vim /etc/init.d/functions
  2. 导入函数到当前shell : source /etc/init.d/functions
1
2
3
4
5
6
[root@zhuuu ~]# vim /etc/init.d/functions 
[root@zhuuu ~]# echo_success
-bash: echo_success: command not found
[root@zhuuu ~]# source /etc/init.d/functions
[root@zhuuu ~]# echo_success
[root@zhuuu ~]# [ OK ]
打赏
  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2019-2022 Zhuuu
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信