实验室 3:启动和启动进程¶
目标¶
完成此实验后,您将能够
- 手动控制某些启动进程和服务
- 自动控制服务
完成此实验的估计时间:50 分钟
启动进程概述¶
本实验的练习将从启动过程一直到用户登录。这些步骤将检查并尝试自定义启动过程的部分。启动过程的高级步骤是:
步骤摘要¶
- 硬件加载,读取并执行引导扇区
- 引导加载程序被执行 (大多数 Linux 发行版上是 GRUB)
- 内核解压并被执行
- 内核初始化硬件
- 内核挂载根文件系统
- 内核将 /usr/lib/systemd/systemd 作为 PID 1 执行
systemd
启动启动过程中需要的以及配置为运行默认启动目标的单元getty
程序在每个定义的终端上启动getty
提示登录getty
执行 /bin/login 来验证用户- 登录启动 shell
systemd
¶
systemd
是 Linux 操作系统的系统和服务管理器。
systemd
单元¶
systemd
提供了一种名为“单元”的各种实体之间的依赖关系系统。单元封装了系统启动和维护所需的各种对象。大多数单元都配置在所谓的单元配置文件中——纯文本 ini 风格的文件。
systemd
单元的类型¶
systemd
定义了以下 11 种单元类型:
服务单元 启动和控制守护进程及其组成进程。
套接字单元 封装系统中的本地 IPC 或网络套接字,用于基于套接字激活。
目标单元 用于对其他单元进行分组。它们在启动过程中提供众所周知的同步点。
设备单元 在 systemd
中公开内核设备,并可用于实现基于设备的激活。
挂载单元 控制文件系统中的挂载点。
自动挂载单元 提供自动挂载功能,用于按需挂载文件系统以及并行启动。
计时器单元 有助于根据计时器触发其他单元的激活。
交换单元 与挂载单元非常相似,封装了操作系统的内存交换分区或文件。
路径单元 在文件系统对象发生更改或修改时,可能会激活其他服务。
切片单元 可用于分组管理系统进程 (如服务和作用域单元) 的单元,在一个分层树中进行资源管理。
作用域单元 与服务单元类似,但管理的是外部进程而不是启动它们。
练习 1¶
/usr/lib/systemd/systemd | PID=1¶
历史上,init 曾有过许多名称,并采取过多种形式。
无论其名称或实现如何,init (或其等效程序) 通常被称为“所有进程之母”。
“init”的手册页称其为所有进程的父进程。按惯例,内核的第一个程序或进程总是具有进程 ID 1。一旦第一个进程运行,它就会继续启动其他服务、守护进程、进程、程序等。
探索第一个系统进程¶
注意
在下面的练习中,将 PID 替换为进程 ID 号。
-
以任何用户身份登录系统。查询 /proc/PID/comm 虚拟文件系统路径,找出 ID 为 1 的进程的名称。输入:
[root@localhost ~]# cat /proc/1/comm systemd
-
运行
ls
命令查看 /proc/PID/exe 虚拟文件系统路径,查看 ID 为 1 的进程背后的可执行文件的名称和路径。输入:[root@localhost ~]# ls -l /proc/1/exe lrwxrwxrwx 1 root root 0 Oct 5 23:56 /proc/1/exe -> /usr/lib/systemd/systemd
-
尝试使用
ps
命令找出 PID 背后的进程或程序的名称。输入:[root@localhost ~]# ps -p 1 -o comm= systemd
-
使用
ps
命令查看 PID 1 背后的进程或程序的完整路径和任何命令行参数。输入:[root@localhost ~]# ps -p 1 -o args= /usr/lib/systemd/systemd --switched-root --system --deserialize 16
-
要检查“所有进程之母”,传统上称为 init 的进程,实际上是否为 systemd,请使用
ls
来确认init
是否是链接到systemd
二进制文件的符号链接。输入:[root@localhost ~]# ls -l /usr/sbin/init lrwxrwxrwx. 1 root root 22 Aug 8 15:33 /usr/sbin/init -> ../lib/systemd/systemd
-
使用
pstree
命令显示系统进程的树状视图。输入:[root@localhost ~]# pstree --show-pids
练习 2¶
systemd
目标 (运行级别)¶
systemd
定义并依赖许多不同的目标来管理系统。在此练习中,我们将只关注 5 个主要目标。本节中探索的 5 个主要目标在此列出:
- poweroff.target
- rescue.target
- multi-user.target - 以完全的多用户支持但无图形环境的方式启动系统
- graphical.target - 以网络、多用户支持和显示管理器的方式启动系统
- reboot.target
技巧
目标单元取代了经典 SysV init 系统中的 SysV 运行级别。
管理 systemd 目标¶
-
列出服务器上所有 (活动的 + 非活动的 + 失败的) 可用目标。
[root@localhost ~]# systemctl list-units --type target --all
-
仅列出当前活动的目标。输入:
[root@localhost ~]# systemctl list-units -t target
-
使用
systemctl
命令查看/获取系统配置为启动的默认目标的名称。输入:[root@localhost ~]# systemctl get-default multi-user.target
-
查看默认目标 (multi-user.target) 的单元文件内容。输入:
[root@localhost ~]# systemctl cat multi-user.target # /usr/lib/systemd/system/multi-user.target ........ [Unit] Description=Multi-User System Documentation=man:systemd.special(7) Requires=basic.target Conflicts=rescue.service rescue.target After=basic.target rescue.service rescue.target AllowIsolate=yes
注意
multi-user.target
单元中配置的一些属性及其值。例如:Description、Documentation、Requires、After 等。 -
basic.target
单元被列为multi-user.target
的Requires
属性的值。查看basic.target
的单元文件。输入:[root@localhost ~]# systemctl cat basic.target # /usr/lib/systemd/system/basic.target [Unit] Description=Basic System Documentation=man:systemd.special(7) Requires=sysinit.target Wants=sockets.target timers.target paths.target slices.target After=sysinit.target sockets.target paths.target slices.target tmp.mount RequiresMountsFor=/var /var/tmp
-
systemctl cat
命令仅显示给定单元的属性和值的一个子集。要查看目标单元所有属性和值的完整转储,请使用 show 子命令。show
命令还将显示低级属性。显示 multi-user.target 的所有属性,输入:[root@localhost ~]# systemctl show multi-user.target
-
从 multi-user.target 单元的长属性列表中筛选出 Id、Requires 和 Description 属性。输入:
[root@localhost ~]# systemctl --no-pager show \ --property Id,Requires,Description multi-user.target Id=multi-user.target Requires=basic.target Description=Multi-User System
-
查看 multi-user.target 启动时会引入的服务和资源。换句话说,显示 multi-user.target “Wants” 的内容。输入:
[root@localhost ~]# systemctl show --no-pager -p "Wants" multi-user.target Wants=irqbalance.service sshd.service..... ...<SNIP>...
-
使用
ls
和file
命令了解传统init
程序与systemd
程序之间关系的更多信息。输入:[root@localhost ~]# ls -l /usr/sbin/init && file /usr/sbin/init lrwxrwxrwx. 1 root root 22 Aug 8 15:33 /usr/sbin/init -> ../lib/systemd/systemd /usr/sbin/init: symbolic link to ../lib/systemd/systemd
更改默认启动目标¶
-
设置/更改系统启动的默认目标。使用
systemctl set-default
命令将默认目标更改为graphical.target
。输入:[root@localhost ~]# systemctl set-default graphical.target
-
检查新设置的启动目标是否处于活动状态。输入:
[root@localhost ~]# systemctl is-active graphical.target inactive
请注意,即使它被设置为默认值,输出也显示该目标 *未* 活动!
-
要强制系统立即切换并使用给定目标,您必须使用
isolate
子命令。输入:[root@localhost ~]# systemctl isolate graphical.target
警告
systemctl isolate 命令如果使用不当可能会很危险。这是因为它会立即停止在新目标中未启用的进程,可能包括您当前使用的图形环境或终端!
-
再次检查
graphical.target
是否正在使用并且处于活动状态。 -
查询并查看 graphical.target “Wants” 的其他服务或资源。
问题
multi-user.target 和 graphical.target “Wants” 的主要区别是什么?
-
由于您的系统运行的是服务器类操作系统版本,其中可能不需要完整的图形桌面环境,因此请将系统切换回更适合的 multi-user.target。输入:
[root@localhost ~]# systemctl isolate multi-user
-
设置/更改系统的默认启动目标回 multi-user.target。
-
运行一个快速 [且额外] 的手动检查,以查看 default.target 符号链接指向哪个目标,方法是运行:
[root@localhost ~]# ls -l /etc/systemd/system/default.target
练习 3¶
本节的练习将向您展示如何配置可能需要在系统启动时自动启动的系统/用户进程和守护进程 (又称服务)。
查看服务状态¶
-
以 root 用户身份登录时,列出所有类型为 service 的 systemd 单元。输入:
root@localhost ~]# systemctl list-units -t service -all
这将显示活动以及已加载但未活动的单元的完整列表。
-
查看服务类型下活动
systemd
单元的列表。[root@localhost ~]# systemctl list-units --state=active --type service UNIT LOAD ACTIVE SUB DESCRIPTION atd.service loaded active running Job spooling tools auditd.service loaded active running Security Auditing Service chronyd.service loaded active running NTP client/server crond.service loaded active running Command Scheduler dbus.service loaded active running D-Bus System Message Bus firewalld.service loaded active running firewalld - dynamic firewall daemon ...<SNIP>...
-
缩小范围,详细了解上一个输出中的一个服务——crond.service 的配置。输入:
[root@localhost ~]# systemctl cat crond.service
-
检查
crond.service
是否配置为在系统启动时自动启动。输入:[root@localhost ~]# systemctl is-enabled crond.service enabled
-
查看
crond.service
服务的实时状态。输入:[root@localhost ~]# systemctl status crond.service
默认情况下,输出将包括最近的 10 条 journal 行/条目/日志。
-
查看
crond.service
的状态,并抑制显示任何 journal 行。输入:[root@localhost ~]# systemctl -n 0 status crond.service
-
查看 sshd.service 的状态。
问题
查看
firewalld.service
的状态。firewalld.service
单元是什么?
停止服务¶
-
仍以具有管理员权限的用户身份登录时,使用
pgrep
命令查看crond
进程是否出现在系统上运行的进程列表中。[root@localhost ~]# pgrep -a crond 313274 /usr/sbin/crond -n
如果找到匹配的进程名称,
pgrep
命令应该会找到并列出crond
的 PID。 -
使用
systemctl
停止crond.service
单元。输入:[root@localhost ~]# systemctl stop crond.service
命令应该完成,没有输出。
-
使用
systemctl
查看crond.service
的状态,以查看您的更改效果。 -
再次使用
pgrep
查看crond
进程是否仍然出现在进程列表中。
启动服务¶
-
以管理员用户帐户登录。使用
pgrep
命令查看crond
进程是否出现在系统上运行的进程列表中。[root@localhost ~]# pgrep -a crond
如果
pgrep
找到匹配的进程名称,它将列出crond
的 PID。 -
使用
systemctl
启动crond.service
单元。输入:[root@localhost ~]# systemctl start crond.service
命令应该完成,没有输出或可见反馈。
-
使用
systemctl
查看crond.service
的状态,以查看您的更改效果。输入:[root@localhost ~]# systemctl -n 0 status crond.service ● crond.service - Command Scheduler Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2023-10-16 11:38:04 EDT; 54s ago Main PID: 313451 (crond) Tasks: 1 (limit: 48282) Memory: 1000.0K CGroup: /system.slice/crond.service └─313451 /usr/sbin/crond -n
问题
从您系统上
systemctl
status 命令的输出中,crond
的 PID 是多少? -
同样,再次使用
pgrep
查看crond
进程是否现在出现在进程列表中。比较 pgrep 显示的 PID 与上一个systemctl
statuscrond.service
中显示的 PID。[root@localhost ~]# systemctl is-enabled crond.service enabled
重启服务¶
对于许多服务/守护进程,在对其底层配置文件进行更改后,重新启动或重新加载正在运行的服务/守护进程通常是必要的。这是为了使给定的进程/服务/守护进程能够应用最新的配置更改。
-
查看 crond.service 的状态。输入:
[root@localhost ~]# systemctl -n 0 status crond.service
在输出中,记下
crond
的 PID。 -
运行
systemctl restart
来重启crond.service
。输入:[root@localhost ~]# systemctl -n 0 status crond.service
命令应该完成,没有输出或可见反馈。
-
再次检查 crond.service 的状态。将最新的 PID 与您在步骤 1 中记下的 PID 进行比较。
-
使用
systemctl
检查crond.service
当前是否处于活动状态。输入:[root@localhost ~]# systemctl is-active crond.service active
问题
您认为每次重启服务时 PID 都会不同,这是为什么?
技巧
旧的经典 service 命令的功能已被移植到 systemd 管理的系统上,可以无缝工作。您可以使用如下的 service 命令来停止、启动、重启和查看
smartd
服务的状态。# service smartd status # service smartd stop # service smartd start # service smartd restart
禁用服务¶
-
使用
systemctl
检查crond.service
是否已启用以在系统启动时自动启动。输入:[root@localhost ~]# systemctl is-enabled crond.service enabled
示例输出显示已启用。
-
禁用
crond.service
的自动启动。输入:[root@localhost ~]# systemctl disable crond.service Removed /etc/systemd/system/multi-user.target.wants/crond.service.
-
再次运行
systemctl is-enabled
命令查看您的更改效果。问题
在您需要远程管理的服务器上,为什么您不希望禁用
sshd.service
之类的服务,使其在系统启动时自动启动?
确保禁用 (屏蔽) 服务¶
尽管您在之前的练习中看到了可以使用 systemctl disable
命令来禁用服务,但其他 systemd
单元 (进程、服务、守护进程等) 如果需要,可能会悄悄地重新启用已禁用的服务。这可能发生在当一个服务依赖于另一个 [已禁用] 服务时。
您应该屏蔽服务以确保禁用 systemd
服务单元,并防止意外重新激活。
-
使用
systemctl
来屏蔽crond.service
,并防止任何不期望的重新激活,输入:[root@localhost ~]# systemctl mask crond.service Created symlink /etc/systemd/system/crond.service → /dev/null.
-
运行
systemctl is-enabled
命令查看您的更改效果。[root@localhost ~]# systemctl is-enabled crond.service masked
-
要撤销您的更改并取消屏蔽
crond.service
,请使用systemctl unmask
命令,运行:[root@localhost ~]# systemctl unmask crond.service Removed /etc/systemd/system/crond.service.
启用服务¶
-
使用
systemctl
检查crond.service
单元的状态。输入:[root@localhost ~]# systemctl status crond.service
服务仍然应该是停止状态。
-
使用
systemctl enable
命令启用crond.service
以自动启动。输入:[root@localhost ~]# systemctl enable crond.service Created symlink /etc/systemd/system/multi-user.target.wants/crond.service → /usr/lib/systemd/system/crond.service.
-
再次使用
systemctl
检查crond.service
是否处于活动状态。输入:[root@localhost ~]# systemctl is-active crond.service inactive
问题
您刚刚启用了
crond.service
。为什么它没有运行或在前面的命令中未被列为活动状态? -
使用
systemctl enable
命令的一个稍有不同的变体来启用crond.service
并立即启动守护进程。输入:[root@localhost ~]# systemctl --now enable crond.service
-
检查
crond.service
是否现在处于活动状态。输入:[root@localhost ~]# systemctl is-active crond.service active
-
使用
systemctl
,确保crond.service
已启动、正在运行并已启用自动启动。
作者:Wale Soyinka
贡献者:Steven Spencer, Ganna Zhyrnova