Linux 基础学习训练教材 - RockyLinux 9.x

第 7 堂课:认识 bash 基础与系统救援

文本界面的操作软件就是 shell,缺省 RockyLinux 使用的是 bash,所以一定要了解才行!另外,如何救援系统,也再次探讨一下!

最近更新时间: 2023/02/26

前一节课谈到文件系统且最终有一个简单的文件系统错误救援。但如果发生严重问题时该如何是好?此时可能需要一个简易的救援模式, 包括通过 systemd 以及直接取得一个 bash 来处理。而前面所有的章节,我们都会使用到的文本界面终端机,那就是 bash!这一小节, 我们将比较完整的介绍一下 bash 的相关用法,让大家归纳一下之前学的东西,以及更深入讨论看看!

7.1:bash shell 基础认识

之前课程讲过登录系统取得的文本型交互界面就称为 shell,shell 的操作环境能够依据用户的喜好来设置,用户也能够切换不同的 shell。 而 shell 最重要的就是变量,这在许多的编程语言里面都是需要注意到的部份。

7.1.1:系统与用户的 shell

系统所有合法的 shell 都在 /etc/shells 这个文件内,读者可以查找该文件的内容。在 /etc/shells 常见的合法 shell 如下:

  • /bin/sh (已经被 /bin/bash 所取代)
  • /bin/bash (就是 Linux 缺省的 shell)
  • /bin/tcsh (集成 C Shell ,提供更多的功能)
  • /bin/csh (已经被 /bin/tcsh 所取代)
我们的训练机因为只安装基础的 Linux 系统,并没有安装 C shell,所以当你 cat /etc/shells 时,只有看到 bash 与 sh 而已喔! 如果有安装 C shell 的话,那就会将额外的 shell program 写入到这个文件当中了!

因为有许多软件会使用到系统上的 shell,但又担心用户或者是恶意攻击者会使用怪异的有问题的 shell 来操作软件。因此某些软件在判断 shell 的合法性, 亦即直接参考 /etc/shells 的规范,来判断所谓的合法与不合法。

读者从之前的系统登录行为中,应该知道在文本界面登录后系统会给予一个 shell,而在图形界面时,也能够借由按下『终端机』来取得 shell 的操作。 但取得的缺省 shell 是哪一个?需要从用户的设置数据里面搜索。请参考 /etc/passwd 里面,使用冒号 (:) 分隔的第 7 个字段,就是该帐号缺省取得的 shell。

例题 7.1.1-1:查找合法的 shell 有哪些
  1. 请使用 cut 这个指令,将 /etc/passwd 这个文件的内容中,以冒号 (:) 为分隔字符 (delimiter),将第 1 及第 7 字段 (field) 输出到屏幕上
  2. 承上,找到关键字为 daemon 的那一行,daemon 用户所使用的 shell 是什么?

用户可以自由的切换所需要的 shell,不过不同的 shell 使用的方式、语法都有点差异。举例来说, bash 使用的变量设置方式为 『var='content'』, 但是 csh 使用的是『 set var = 'content' 』,csh 需要有 set ,不过等号两边可以有空格。但是 bash 虽然不用 set ,但是等号两边不可以直接加空格, 这就有不一样的的地方。

  • 不同 shell 的切换

其实, shell 就是一只可以交互的程序而已,因此,基本上是可以互相调用而切换 shell 界面的!只是我们的 RockyLinux 9 缺省只有安装 bash 而已, 因此进行底下的测试之前,需要安装额外的 shell 才行。

例题 7.1.1-2 :练习不同 shell 的切换
  1. 安装额外的 C shell 界面:
    1. 请先激活虚拟机的网络环境,并确认互联网为正常使用
    2. 使用 root 的身份,安装 tcsh 这个软件
    3. 确认一下 /etc/shells 有没有加入 csh 成为合法的 shell 呢
  2. 在 bash 软件环境下,操作确认 shell 名称的指令:
    1. 请使用 student 身份登录系统,取得终端机后,使用『 echo $BASH 』的方式查阅有没有这个变量以及其输出的内容
    2. 请输入『 echo $shell 』观察有没有数据输出?
    3. 使用『 echo $0 』观察输出的数据是什么?
  3. 切换到 c shell 查看一下确认 shell 名称的指令:
    1. 使用『 /bin/csh 』切换 shell 成为 c shell
    2. 分别使用『 echo $BASH 』与『 echo $shell 』观察输出的数据为何?
    3. 使用『 echo $0 』观察输出的数据是什么?
    4. 先通过『 exit 』离开 c shell 之后,再次以 echo $0 观察目前的 shell 名称为何?
  4. 运行『 /sbin/nologin 』看看输出的数据为何?

用户可以通过直接输入 shell 的运行档 (例如上述的 /bin/csh) 来直接切换到新的 shell 去工作,而想要确认目前的 shell 是什么, 最简单的方式就是使用『 echo $0 』列出目前的运行档。 另外,系统的用户帐号数据纪录在 /etc/passwd 当中,该文件里面竟然有 /sbin/nologin 这个 shell 呢! 这个 shell 就是给系统帐号缺省使用的不可交互的 shell !但是很奇怪,这个 /sbin/nologin 并没有写入 /etc/shells ,所以基本上,不能称为合法的 shell 喔!

例题 7.1.1-3:尝试修改用户的缺省 shell 程序 (使用 root 身份进行底下的处理)
  1. 用 usermod 来修改 student 的 shell 变成 /sbin/nologin
  2. 使用 su - student 之类的方式,尝试切换身份成为 student
  3. 再次以 usermod 的方式将 student 的 shell 改回来 /bin/bash

为何系统上需要有 /sbin/nologin 这个 shell 呢?

  • 系统上面原本就有很多的软件在运行,这些软件各自有各自的功能,尤其是很多的服务软件,需要的都是一些常驻程序 (daemon)。 这些 daemon 程序,最好都不要使用特权帐号 (指的就是 root 啦) 来运行,这样在 daemon 不小心被攻破时,该进程的拥有者因为不是 root, 比较不会造成太大的系统危害。也因为这样,Linux 里面就有很多的系统帐号,包括前几章都会用到的 sshd, bin, daemon 等帐号! 就是一些系统帐号啦!
  • 这些系统帐号毕竟还是 Linux 里面的实体帐号~如果这些帐号被小心的给予密码 (错误的设置),将可能造成某些人通过这些帐号尝试登录/攻破你的 Linux 系统,因此,这些系统帐号,应该都是要给予限制的帐号 (restricted account)。所以,我们就给这些帐号无法交互的 shell! 那就是 /sbin/nologin 的用途!也就是,当你尝试 su - daemon 时,系统会回报帐号无法使用啰!
  • 所谓的合法的 shell,也就是写入到 /etc/shells 的壳程序们,一般来说,非限制的用户 (unrestricted account) 所使用的 shell 就是合法的 shell 了!如果将 /sbin/nologin 写入到 /etc/shells 里面,那将代表 sshd, bin, daemon 等系统帐号具有合法的 shell, 即使这个 shell 是无法使用的~根据某些资安文档的说法,这很可能会造成一些漏洞攻击的可能性。因此,缺省的情况下, /sbin/nologin 不再写入于 /etc/shells 当中了!(可以参考:https://access.redhat.com/errata/RHSA-2018:3249)
  • 另外,如果你创建的一般终端用户,使用的服务并不包含取得可跟系统交互的 bash / csh 等,例如单纯的 FTP / mail 帐号, 那也可以使用 /sbin/nologin 成为缺省的 shell,这些终端帐号还是可以通过特别的设置,来取得 ftp, email 等服务的!
例题 7.1.1-4:创建系统帐号给予的 shell 方式
  1. 针对 /sbin/nologin 以及一般 shell program 的登录者差异:
    1. 使用 id 这个指令检查系统有无 bin 与 student 这两个帐号的存在?
    2. 能不能在不知道密码的情况下,使用 root 切换成 student 这个帐号?为什么?
    3. 能不能在不知道密码的情况下,使用 root 切换成 bin 这个帐号?为什么?
  2. 创建一个不能取得交互 shell 的帐号
    1. 创建一个不可登录系统取得交互 shell 的帐号,帐号名称为 puser1,密码为 MyPuser1
    2. 尝试使用 root 切换成为这个帐号测试一下结果

7.1.2:变量设置规则

上一小节谈到的『 echo $BASH 』就是变量的功能,bash shell 会主动的创建 BASH 这个变量,且其内容就是 /bin/bash, 方便读者了解到目前的 shell 是哪只程序达成的。那如何设置变量呢?简单的设置方式与调用方式为:

[student@localhost ~]$ 变量="变量内容"
[student@localhost ~]$ echo $变量
[student@localhost ~]$ echo ${变量}

其中变量有许多的设置规则需要遵守:

  • 变量与变量内容以一个等号『=』来链接
  • 等号两边不能直接接空白字符
  • 变量名称只能是英文本母与数字,但是开头字符不能是数字
  • 变量内容若有空白字符可使用双引号『"』或单引号『'』将变量内容结合起来
  • 承上,双引号内的特殊字符如 $ 等,可以保有原本的特性
  • 承上,单引号内的特殊字符则仅为一般字符 (纯文本)
  • 可用转义字符『 \ 』将特殊符号(如 [Enter], $, \, 空白字符, ' 等)变成一般字符
  • 在一串指令的运行中,还需要借由其他额外的指令所提供的信息时,可以使用反单引号『`指令`』或 『$(指令)』。
  • 若该变量为扩增变量内容时,则可用 "$变量名称" 或 ${变量} 累加内容
  • 若该变量需要在其他子进程运行,则需要以 export 来使变量变成环境变量
  • 通常大写字符为系统缺省变量,自行设置变量可以使用小写字符,方便判断 (纯粹依照用户兴趣与嗜好)
  • 取消变量的方法为使用 unset :『unset 变量名称』
例题 7.1.2-1: 设置与调用变量 (使用 student 帐号操作)
  1. 设置一个名为 myname 的变量,变量的内容为『 peter pan 』
  2. 使用 echo 调用出 myname 的内容
  3. 是否能够设置 2myname 的内容为『 peter pan 』呢?
  4. 设置 varsymbo 变量的内容为『 $myname 』,$myname 就是纯文本数据不是变量 (不是 peter pan)。设置完毕后调用出来
  5. 设置 hero 变量的内容为『 I am $myname 』,其中 $myname 会依据 myname 变量的内容而变化。设置完毕请调用出来。
  6. 使用 uname -r 秀出目前的内核版本
  7. 设置 kver 变量,内容为『 my kernel version is N.xx 』,其中 N.xx 为 uname -r 输出的信息。请注意, kver 变量设置过程中,需要用到 uname -r 这个指令的协助,意思是,该项目为变动的!

变量设置的过程当中,使用子指令『 $(command) 』的操作为相当重要的。例如底下的案例中,管理员可以很快速的找到前一堂课谈到的特殊权限文件并列出该文件的权限:

例题 7.1.2-2:通过子指令 $() 来处理数据的流程 (使用 student 帐号操作)
  1. 使用 man find 找出 -perm 的功能为何?
  2. 使用『 find /usr/bin /usr/sbin -perm /6000 』找出所有含有特殊权限的文件名
  3. 使用『 ls -l $(find /usr/bin /usr/sbin -perm /6000) 』将所有文件名的权限列出

如上的第 3 个范例,读者可以将第 1 个范例的文件名找到后,一个一个以 ls -l 去查找权限,不过性能与时间花费太多。 此时通过子指令的功能即可快速的找到相对应的数据。底下亦为常见的操作功能:

例题 7.1.2-3:同样通过子指令来处理 (使用 student 帐号操作)
  1. 使用 find 的功能,找出在 /usr/sbin 及 /usr/bin 底下权限为 4755 的文件
  2. 创建 ~/unit07/ 目录
  3. 将步骤 1 找到的文件连同权限拷贝到 ~/unit07 目录下。

7.1.3:影响操作行为的变量

某些变量会影响到用户的操作行为,许多变量之前曾经提及,本节集中说明。

变量功能
LANG
LC_ALL
语系数据,例如使用 date 输出信息时,通过 LANG 可以修改输出的消息数据。
PATH 运行档搜索的路径~目录与目录中间以冒号(:)分隔,由于运行档/指令的搜索是依序由 PATH 的变量内的目录来查找,所以,目录的顺序也是重要的。
HOME 代表用户的家目录,亦即用户看到的 ~ 代表的目录。
MAIL 当我们使用 mail 这个指令在收信时,系统会去读取的邮件信箱文件 (mailbox)。
HISTSIZE 这个与『历史命令』有关。我们曾经下达过的指令可以被系统记录下来,而记录的『笔数』则是由这个值来设置的。
RANDOM 『随机乱数』的变量。目前大多数的 distributions 都会有乱数产生器,亦即 /dev/random 文件。读者可以通过这个乱数文件相关的变量 ($RANDOM) 来随机取得乱数。在 BASH 的环境下,RANDOM 变量的内容介于 0~32767 之间,所以,你只要 echo $RANDOM 时,系统就会主动的随机取出一个介于 0~32767 的数值。
PS1 命令提示字符,可使用 man bash 搜索 PS1 关键字,即可了解提示字符的设置方式。
? $? 这个变量内容为指令的回传值,当回传值为 0 代表指令正常运作结束,当不为 0 则代表指令有错误。

比较需要注意到的变量是 PATH 路径搜索变量,他会影响到用户操作的行为,设置错误会有相当严重的后果。

例题 7.1.3-1: 关于 PATH 的重要性,不同帐号的使用
  1. 使用系统管理员的身份处理与设置相关变量数据:
    1. 印出 PATH 这个变量的内容,并观察每个项目中间的分隔符号为何?
    2. 设置一个名为 oldpath 的变量,内容就是 ${PATH}
    3. 设置 PATH 的内容成为 /bin 而已 (非常重要,不可设错!)
    4. 此时输入以前曾操作过得 useradd --help 及 usermod --help 等指令,屏幕显示的消息为何?
    5. 若使用 /sbin/usermod --help,可以正常显示嘛?
    6. 请设置 PATH 的内容成为 ${oldpath} ,恢复正常的路径数据。
  2. 以一般帐号 student 的身份来运行下列的练习动作:
    1. 创建 ~student/cmd/ 目录,且将 /bin/cat 拷贝成为 ~student/cmd/scat
    2. 输入『 ~student/cmd/scat /etc/hosts 』确认指令正常无误。
    3. 输入『 scat /etc/hosts 』会发生什么问题?
    4. 如何让 student 用户直接使用 scat 而不须使用 ~student/cmd/scat 来运行?
由于 PATH 设置错误时,可能会导致系统的 crash 状态,尤其是当 PATH 并未含有 /bin 这个搜索路径时,有相当高的几率会造成 Linux 系统的当机。 因此,在上述的练习中,PATH 的设置请务必小心谨慎!

命令提示字符在每个系统中都不一样,但那是可以修改的,就通过 PS1 这个变量来修改即可。

例题 7.1.3-2: 认识 PS1 这个变量的使用情境
  1. 调用出 PS1 这个变量的内容
  2. 请查找上述变量内容当中 \W 及 \$ 的意义为何 (请 man bash 通过 PS1 关键字查找)
  3. 假设操作者已经做了 15 个指令,则命令提示字符输出如:『 [student@localhost 15 ~]$ 』该如何设置 PS1?

7.1.4:区域/全域变量、父进程与子进程

变量是有使用范围的,一般来说变量的使用范围分为:

  • 区域变量:变量只能在目前这个 shell 当中存在,不会被子进程所沿用
  • 全域变量:变量会保存在一个共用的内存空间,可以让子进程继承使用。

如 7.1.2 当中提到的将变量提升成为全域变量的方式为通过 export,观察可用 env 或 export 来观察。

例题 7.1.4-1: 了解区域变量、全域变量、父进程、子进程间的关系 (使用 student 帐号即可)
  1. 在父进程运行底下的动作,找寻区域变量与全域变量
    1. 使用 set 或 env 或 export 观察是否存在 mypp 这个变量?
    2. 设置 mypp 的内容为『 from_ppid 』,并且调用出来
    3. 使用 set 或 env 或 export 观察是否存在 mypp 这个变量?
  2. 变成子进程并持续讨论变量:
    1. 运行『 /bin/bash 』进入下一个 bash 的子进程环境中
    2. 使用 set 或 env 或 export 观察是否存在 mypp 这个变量?同时说明为什么?
    3. 设置 mypp2 的内容为『 from_cpid 』,并且调用出来
    4. 使用『 exit 』离开子进程回到原本的父进程
  3. 在父进程处理全域变量,测试 export 的功能:
    1. 观察是否存在 mypp2 这个变量?为什么?
    2. 使用『 export mypp 』后,使用 env 或 export 观察是否存在?
  4. 切换成为子进程,并确认全域变量的存在:
    1. 运行『 /bin/bash 』进入下一个 bash 的子进程环境中
    2. 使用 set 或 env 或 export 观察是否存在 mypp 这个变量?同时说明为什么?
    3. 回到原本的父进程中。

基本上,由原本的 bash 衍生出来的进程都是该 bash 的子进程,而 bash 可以运行 bash 产生一只 bash 的子进程,两只 bash 之间仅有全域变量 (环境变量) 会带给子进程, 而子进程的变量,基本上是不会回传给父进程的。

7.1.5:使用 kill 管理进程

某些时刻管理员会有想要手动移除某些特定进程的时刻发生,例如某些很占资源的 bash 进程的管理等等,此时就可以通过使用 kill 这个指令来处理。 基本上,kill 并不是『删除』进程,而是给予进程一个『信号 (signal) 』来管理,缺省的信号为 15 号,该信号的功能为『正常关闭进程』的意思。 而想要强制关闭该程序,就得要使用 9 这个号码来处理了。

例题 7.1.5:使用 kill 管理/发送进程的信号 (使用 student 身份)
  1. 使用『 vim checking.txt 』,随便编辑几个字,然后将 vim 进程放进背景中暂停
  2. 使用 jobs -l 进一步列出该进程的 PID 号码
  3. 使用『 kill PID号码 』尝试删除该工作,是否能够生效?
  4. 若无法删除,请使用『 kill -9 PID号码 』的方式来删除,是否能够生效?
  5. 再次使用 vim checking.txt 时,会出现什么消息?如何解决?

若用户有特别的需求需要删除掉某些特定的进程,就可以通过这样的机制来处理。

上面的例题内的动作只是测试而已,基本上不应该如此删除数据!否则容易出问题!另外,由于某些网络莫名的缘故,通过网络进行 vim 编辑时,如果因为断线而导致文件来不及保存,不要太担心喔!通过上面的方式,可以『救援』回复一些数据!

7.1.6:login shell and non-login shell

当读者下达『 echo ${PS1} 』时,应该有发现 PS1 这个影响操作行为的变量已经设置好了,故应该理解为已经有设置档在协助用户登录时规划好操作环境的流程。 而读者应该也会发现到,取得 bash 的情况有很多种,但大致可分为两大类:

  • 一种是需要输入帐号与密码才能够取得 bash 的行为,例如从 tty2 登录,或者是输入『 su - 』来取得某个帐号的使用权,这种情况被称为是 login shell 的变量设置档读取方式。
  • 一种是用户已经取得 bash 或者是其他的交互界面,然后通过该次登录后运行 bash ,例如从图形界面按下终端机、直接在文本界面输入 bash 来取得 bash 子进程、输入『 su 』来切换身份等等,这种方式通常不需要重新输入帐号与密码,因此称为 non-login shell 的变量设置档读取方式。

通常 login shell 读取设置档的流程是:

  1. /etc/profile:这是系统整体的设置,你最好不要修改这个文件;
  2. ~/.bash_profile 或 ~/.bash_login 或 ~/.profile (只会读 1 个,依据优先级决定):属于用户个人设置,你要改自己的数据,就写入这里!

由于 login shell 已经读取了 /etc/profile 因此已经设置了大部分的全域变量设置,所以 non-login shell 只需要少部份的设置即可。 故 non-login shell 只会读取一个个人设置档,亦即是:

  • ~/.bashrc
例题 7.1.6-1:理解 login shell 与 non-login shell 的环境参数读取行为
  1. 观察一下 ~/.bash_profile 的内容,说明该文件设置了什么项目?
  2. 观察 ~/.bashrc 的内容,说明该文件设置了什么项目?

由于 ~/.bash_profile 也是读取 ~/.bashrc ,因此用户只需要将设置放置于家目录下的 .bashrc 就可以让两者读取了。

事实上,也建议你可以前往 /etc/profile 这个文件内容瞧一瞧,看看到底 login shell 读了哪些设置档喔!
例题 7.1.6-2:尝试设置 student 的操作环境
  1. 请在 student 的家目录编辑 .bashrc ,增加底下的项目:
    1. 设置 history 可以输出 10000 笔数据
    2. 设置运行 cp 时,其实会主动加入 cp -i 的选项
    3. 设置运行 rm 时,其实会主动加入 rm -i 的选项
    4. 设置运行 mv 时,其实会主动加入 mv -i 的选项
    5. 增加 PATH 的搜索目录在 ~/cmd 目录 (模仿 .bashrc ,避免重复出现!)
    6. 设置一个变量名称为 kver,其内容是目前的内核版本
    7. 强迫语系使用 zh_TW.utf8 这个项目,且必须要设置为全域变量
    8. 让提示字符项目中,增加时间与操作指令次数的项目。
    9. 使用 wc 指令分析 ~/.bash_history 的行数,将该行数纪录于 h_start 的变量中
  2. 设置完毕后,如何在不注销的情况下,让设置生效?

当用户注销 bash 时,bash 会依据家目录下的 .bash_logout 来进行后续的动作,因此若用户有需要额外进行某些工作时, 可以在此文件中设置。

不过用户应该要特别注意的, .bash_logout 仅会在 login-shell 的环境下,注销才会运行。在 non-login shell 的环境下注销, 这个文件并不会被运作的。

例题 7.1.6-3: 处理 logout 额外运行的任务
  1. 每次注销 bash 时,都会:
    1. (1)使用 date 取得『 YYYY/MM/DD HH:MM 』的格式,并且转存到家目录的 history.log 文件中
    2. (2)使用 history 加上管线命令与 wc 来分析结束时的 history 行数,将该数值设置为 h_end,搭配之前设置的 h_start 开始的行数, 计算出这次运行指令的行数号码 (应该是 h_end - h_start +1 ),设置为 h_now,通过 history ${h_now} 将最新的指令转存到 history.log 当中。
  2. 尝试使用 su - student 来登录 student ,再随意进行数个指令,之后注销 bash 回到原本的 bash 当中,观察 ~/history.log 是否有信息纪录?

7.2:系统救援

我们在前一堂课提到过简易的系统救援,直接以 root 的密码与身份来进入救援模式,然后处理好了文件系统。但万一 root 的 shell 被不小心修改了, 导致无法使用 root 的密码进入系统时,该如何处理?底下的动作比较严重,请读者务必要学会救援的方式。

7.2.1:通过正规的 systemd 方式救援

我们前面讲过许多重要的系统管理,其中包括文件系统与这节课提到的 shell 功能。想一想,如果产生底下的问题时,该如何处理?

  • 文件系统或者是 /etc/fstab 设置档写错了!
  • root 的 shell 被误改成为 nologin,导致无法使用 root 了 (即使知道密码)

要处理这个练习,请先进行如下的动作之后,让系统被破坏,才能够加以练习:

[root@localhost ~]# vim /etc/fstab
/dev/mapper/rocky-home1 /home  xfs  defaults  0 0

[root@localhost ~]# usermod -s /sbin/nologin root
[root@localhost ~]# su -
This account is currently not available.

如此才能够确认 1. 文件系统被破坏以及 2. root 的身份设置错误 (shell 无法使用)。接下来运行 reboot 来看看会出现什么问题。

图 7.2.1-1、因为文件系统与 root 身份出问题的状态
图 7.2.1-1、因为文件系统与 root 身份出问题的状态

如上图所示,开机后出现文件系统状态,系统要求输入 root 密码,虽然用户输入正确的密码了,却无法取得 root 的 bash 操作界面, 因为设置到错误的 shell 了。此时正规的救援模式无法使用,需要用到 systemd 开机流程里面,让系统进入到一个小小的救援操作系统, 该操作系统是仿真出来的,仅仅用来作为挂载文件系统的功能。处理的流程为:

  1. 重新开机,且进入菜单后的五秒内按下方向键,并将光棒选择到第一个开机菜单项目上面
    图 7.2.1-2、光棒的移动与进入编辑模式的参考按钮 (e)
    图 7.2.1-2、光棒的移动与进入编辑模式的参考按钮 (e)
  2. 按下『 e 』来进入菜单编辑画面,如下所示,并且在 linux 那一行的最后面增加『 rd.break 』的项目,之后按下 [Ctrl]+x 来进入救援模式
    图 7.2.1-3、交互编辑内核参数,加入进入救援模式的方案
    图 7.2.1-3、交互编辑内核参数,加入进入救援模式的方案
  3. 救援模式会将根目录挂载到 /sysroot 这个目录下,不过是缺省挂载成唯读,因此管理员请用『 mount -o remount,rw /sysroot 』将该目录重新挂载成可读写, 然后使用『 chroot /sysroot 』将根目录切换到 /sysroot 底下,就可以成功的取用原本的操作系统了。
    图 7.2.1-4重新挂载为可读写,并进行更换根目录的行为 (chroot) 图 7.2.1-4重新挂载为可读写,并进行更换根目录的行为 (chroot) 图 7.2.1-4重新挂载为可读写,并进行更换根目录的行为 (chroot)
    图 7.2.1-4重新挂载为可读写,并进行更换根目录的行为 (chroot)
  4. 此时系统提示字符只有『 sh-5.1# 』也是正常的,请运行『 mount -a 』之后就可以进行『 usermod -s /bin/bash root 』等动作!一般建议动作流程如下:
    [root@localhost ~]# mount -a
    [root@localhost ~]# usermod -s /bin/bash root
    [root@localhost ~]# vim /etc/fstab
    /dev/mapper/rocky-home /home  xfs  defaults  0 0
    
    [root@localhost ~]# touch /.autorelabel 
    [root@localhost ~]# exit
    
  5. 最后使用 reboot 重新开机,就能够正常的开机进入系统环境了。

最后一个步骤之所以要处理 /.autorelabel 这个情况,是因为 Rocky Linux 9 缺省会激活 SELinux 这个安全强化模块,但是此模块在救援模式并没有打开, 所以被更动到的文件在下次开机后,可能会产生无法读取的问题。系统开机会去找 /.autorelabel ,若发现有此文件则会重新写入 SELinux 的相关设置, 因此系统在重新开机的流程中共会启动两次,原因为第一次会重新写入 SELinux 设置,第二次才是正常开机。

图 7.2.1-4、SELinux 的重设过程
图 7.2.1-4、SELinux 的重设过程
根据上课的经验,filesystem 的问题与 user 的问题最好于一次 rd.break 的救援流程中解决,否则由于现有的 Linux 系统进程为平行处理, 若卡在 /home 侦测过 90 秒后,再次进入给予 root 密码的进程中,就会由于无法跑到系统重整 (./autolabel 的动作要求),导致帐号数据密码档无法被读取, 此时系统会 crash 。

7.2.2:通过 bash 直接救援 (Optional)

若读者以前有接触过 Linux 的话,应该知道开机流程中,可以使用 init=/bin/bash 直接让内核调用 bash 来操作系统。 Rocky Linux 9 的 grub2 与 systemd 也保留此功能,此操作行为与 rd.break 相当接近。

  1. 同样在开机过程中,使用第一个开机菜单,然后按下 e 来进入交互编辑模式
  2. 在 linux 那一行的最后面加入 init=/bin/bash 然后按下 [ctrl]+x 来启动
  3. 出现『 bash-5.1# 』之后,进行如下的动作来处理:
    [root@localhost ~]# mount -o remount,rw /
    [root@localhost ~]# mount -a
    [root@localhost ~]# /usr/sbin/usermod -s /bin/bash root
    [root@localhost ~]# /usr/bin/vim /etc/fstab
    [root@localhost ~]# /usr/bin/touch /.autorelabel 
    [root@localhost ~]# /usr/sbin/reboot -f
    
图 7.2.2-1、直接使用 bash 救援!
图 7.2.2-1、直接使用 bash 救援!

这个方案让 Linux 内核主要去调用 bash 来运行,因为内核缺省使用 root 权限,所以调用的 bash 就会是 root 用户来操作。 只是因为非正规使用这个 bash 环境,所以连 PATH 恐怕都没有完整的加载!因此操作指令时,就得要使用绝对路径来处理。 另外,也因为系统非正规使用,所以不是使用缺省的 systemd,不能直接使用 reboot 来重新开机。不过还好, reboot 可以加上 -f (/usr/sbin/reboot -f) 来略过 systemd 的控制,这样就可以直接重新开机了!

除非正常流程已经无法解决,否则尽量不要使用此方法救援。

7.3:课后练习操作

  • 上课的课后练习,非作业:
  1. 变量的相关操作 (全部用 root 身份进行)
    1. 将 /bin/false, /bin/true 等文件设置为系统合法的 shell
    2. 使用 usermod -s [tab][tab] 出现什么?可能的意义是什么?
    3. 将 /bin/false, /bin/true 移除合法 shell 的列表中。
    4. 查看目前 /etc/passwd 当中,有哪些帐号是可以使用 bash 登录系统的?
    5. 目前有哪些全域变量存在
    6. 显示出 PS1 的内容
    7. 将 PS1 的内容改成类似『 C:\win> 』,再测试看看,测试完毕就改回原本的 PS1 喔
    8. 显示出目前的 PATH 内容
    9. 让 PATH 延伸到支持 /opt/bin 目录
    10. 设置 kver 为 uname -r 的输出结果
    11. 将 kver 设置成为全域变量
    12. 由 man 7 signal 找到 1 号是在干麻的?
    13. 通过上述的功能,找到 rsyslog 这个软件的 PID,并对他下达 signal 1 的信号
    14. 查看一下 /var/log/messages 出现了什么消息?
    15. 再由 man 7 signal 找到 SIGTSTP 与 SIGINT 分别是几号?其中 SIGINT 其实是 [ctrl]+c 而 SIGTSTP 就是 [ctrl]+z 的意思。
    16. 开另外一个 bash 窗口,并且激活 vim 软件
    17. 由原本的 root 环境,找到 vim 的 PID,并且尝试将该 PID 放入背景暂停中,并查阅另一个窗口的结果
    18. 使用 $(( )) 的功能,计算一天共有几秒钟?
  • 作业 (不提供学生答案,仅提供教师参考答案)

作业硬盘一般操作说明:

  • 打开云端虚拟机前,请务必确认你打开的硬盘是『unit07』,否则就会做错题目
  • 若要使用图形界面,请务必使用 student 身份登录,若需要切换身份,再激活终端机处理。
  • 若有简答题需要使用中文,请自行以第一堂课的动作自行处理输入法安装。
  • 每部虚拟机均有独特的网卡地址,请勿使用他人硬盘上传,否则计分为 0 分。
  • 每位同学均有自己的 IP 尾数,请先向老师询问您的 IP 尾数,才可以进行作业上传。
  • 最终上传作业结果,请务必使用 root 身份上传。
  • 进入作业硬盘后,先用 root 身份运行 vbird_book_setup_ip , 运行流程请参考:vbird_book_setup_ip

作业当中,某些部份可能为简答题~若为简答题时,请将答案写入 /home/student/ans.txt 当中,并写好正确题号,方便老师订正答案。 请注意,文件名写错将无法上传!

请使用 root 的身份进行如下实做的任务。直接在系统上面操作,操作成功即可,上传结果的程序会主动找到你的实做结果。

  1. (30%) 整体操作系统救援:
    • 问题: 因为某些缘故,目前这个操作系统应该是无法顺利开机的。请使用本节课程所介绍的方式来进行系统的救援。
    • 思考: 根据猜测,可能的原因与 (1)管理员曾经动过 chsh 这个指令有关, (2)管理员似乎也更动过 fstab 这个设置档。
    • 救援: 请依据这些之前的可能举动,来恢复系统的可登录状态。
    • 注意提醒: 千万不要忘记 .autorelabel 的动作!
    • 成功开机登录后: 顺利登录系统后,再使用 root 身份处理 vbird_book_setup_ip 的脚本设置。
  2. (10%) 请处理底下帐号与 shell 的相关事宜:
    1. (3%) 请将系统中的 /bin/false 与 /bin/true 这两个文件变成合法的 shell
    2. (3%) 请将 examuser1 的 shell 变成 /bin/true
    3. (4%) 因为你即将创建一个 FTP 服务器,这个服务器上面的用户只能单纯的使用 FTP 功能,因此你想要让这些帐号无法使用 shell。 假设两个帐号名为 myuser1, myuser2 的帐号,这两个帐号将无法使用交互界面操作系统,且密码均为 MyPassWordhehe
  3. (10%) 通过 bash shell 的功能,进行文件的查找与拷贝
    1. (5%) 找出系统中文件拥有者为 examuser1 的文件名,并将这些找到的文件名(含权限)拷贝到 /root/findout/ 目录内
    2. (5%) 找出在 /usr/sbin 及 /usr/bin 底下权限为 4755 的文件,并将这些文件拷贝到 /root/findperm/ 目录内
  4. (5%) 写一只『大家都能运行的脚本程序』,运行名称为:『 myps 』,运行该指令,其实输出为数据是:『 ps -eo pid,pri,ni,args 』。 请注意: (1)这只程序定义为『本机全部用户都能运行』,所以应该与 bin 有关,不是 sbin! (2)用户在任何工作目录,只要在提示字符输入 myps 即可获得『ps -eo pid,pri,ni,args』的输出结果。
  5. (45%) 特别的帐号成立行为要处理的:
    1. (3%) 创建名为 examuser10 的帐号,密码为 MyPassWordhehe,且这个帐号登录后,缺省会有后续的一些基础设置
    2. 登录行为:(注意,如果用户的 shell 不是 bash,那这个题组就算全错喔!)
      1. (3%) 缺省使用 bash 作为 shell
      2. (3%) 会读入 /etc/examvar 设置档
      3. (3%) 拥有一个名为 myip 的变量,变量内容为『 ifconfig | grep 'inet ' | cut -d 't' -f 2 | cut -d ' ' -f 2 』 的运行成果 (每个同学操作指令的结果都不会相同,但是指令会是一样的)
      4. (3%) 使用 C 语系数据
      5. (3%) 增加 ~examuser10/scripts/ 目录作为指令运行时所寻找的目录位置
      6. (3%) 命令提示字符增加时间项目在里面 (提示字符有点像『[examuser10@localhost 14:37:31 ~]# 』)
      7. (3%) 缺省历史命令纪录 5000 笔,文件纪录也会是 5000 笔
      8. (3%) 操作 cp 时,自动给予 cp -i 的选项
      9. (3%) 通过『 wc -l ~/.bash_history | cut -d ' ' -f 1 』的指令取得前一次登录的历史命令次数, 并将该数值转存到 ~/.history_start 文件内(这个文件每次都覆盖)
    3. 注销的行为:
      1. (3%) 通过『 history | tail -n 1 | awk '{print $1}' 』取得最后一笔历史纪录,然后将该数值指定为 hist_end 变量
      2. (3%) 请使用『 cat ~/.history_start 』取得登录时记载的历史命令笔数,将该数值指定为 hist_start 变量
      3. (3%) 设置一个名为 hist_size 的变量,内容为 hist_end - hist_start 的数值 (有多种计算方式,能成功即可!)
      4. (3%) 将离开的日期,使用『 YYYY/MM/DD HH:MM 』的格式累加写入到 ~/history.log 文件中
      5. (3%) 通过『 history $hist_size 』取得最后最新的数笔纪录后,将该数据累加到 ~/history.log 文件中。

作业结果传输:请以 root 的身分运行 vbird_book_check_unit 指令上传作业结果。 正常运行完毕的结果应会出现【XXXXXX_aa:bb:cc:dd:ee:ff_unitNN】字样。若需要查阅自己上传数据的时间, 请在操作系统上面使用浏览器查找: http://192.168.251.254 检查相对应的课程文件。 相关流程请参考: vbird_book_check_unit

修改历史:
  • 2023/02/26:修改了 /sbin/nologin 的说明,重新 rockylinux 救援画面截屏,同时修订了 reboot -f 的功能!
2023/02/26 以来统计人数
计数器
其他链接
环境工程模式篇
鸟园讨论区
鸟哥旧站

今日 人数统计
昨日 人数统计
本月 人数统计
上月 人数统计