[TOC]
# 控制啟動過程
## 目標:
能夠影響啟動過程并且能夠使用 systemd 目標來修復常見的啟動問題。
選擇 systemd 目標
systemd 目標是一組應在啟動后達到所需狀態的 systemd 單元。下表中列出了重要目標。
| 目標 | 用途 |
| --- | --- |
| graphical.target | 系統支持多用戶、圖形和基于文本的登錄。 |
| multi-user.target | 系統僅支持多用戶、基于文本的登錄。 |
| rescue.target | sulogin 提示,表示基本系統初始化完成。 |
| emergency.target | sulogin 提示,表示 initramfs 回轉完成,且系統 root 以只讀形式掛載于 / 上。 |
某個目標可能屬于另一目標;例如,graphical.target 包含 multi-user.target,后者反過來取決于 base.target 和其他目標。使用以下命令可從命令行查看這些依賴關系:
~~~
[root@serverX~]# systemctl list-dependencies graphical.target | grep target
~~~
使用以下命令可查看所有可用目標的概述:
~~~
[root@serverX~]# systemctl list-units --type=target --all
~~~
使用以下命令可查看磁盤上安裝的所有目標的概述:
~~~
[root@serverX~]# systemctl list-unit-files --type=target --all
~~~
#### 在運行時選擇目標
在運行的系統中,管理員可以隨意使用 systemctl isolate 命令來切換到其他目標;例如,systemctl isolate multi-user.target。
### 注意
并非所有目標都能隔離。只有單元文件中設置了 AllowIsolate=yes 的目標才可以隔離;例如 graphical.target 目標可以隔離,但 cryptsetup.target 目標不能隔離。
#### 設置默認目標
在系統啟動且將控制權從 initramfs 交給 systemd 后,systemd 會嘗試激活 default.target 目標。通常,default .target 目標是(/etc/systemd/system/ 中)指向 graphical.target 或 multi-user.target 的符號鏈接。
systemctl 工具提供了兩個命令來管理鏈接:get-default 和 set-default。
~~~
[root@serverX~]# systemctl get-default
multi-user.target
[root@serverX~]# systemctl set-default graphical.target
rm '/etc/systemd/system/default.target'
ln -s '/usr/lib/systemd/system/graphical.target' '/etc/systemd/system/default.target'
[root@serverX~]# systemctl get-default
graphical.target
~~~
在啟動時選擇其他目標
要在啟動時選擇其他目標,可從啟動加載器將特殊選項附加到內核命令行:systemd.unit=。例如,要將系統啟動到救援Shell,請在交互式啟動加載器菜單中傳遞以下選項:
~~~
systemd.unit=rescue.target
~~~
要使用這種選擇其他目標的方法,請針對 Red Hat Enterprise Linux 7 系統執行以下步驟:
1. (重新)啟動系統。
2. 按任意鍵中斷啟動加載器菜單倒計時。
3. 將光標移至要啟動的條目。
4. 按 e 編輯當前條目。
5. 將光標移至 linux16 開頭的行。此為內核命令行。
6. 附加 systemd.unit=desired.target。
7. 按 Ctrl+x 使用這些更改進行啟動。
## 恢復 root 密碼
在仍以管理員或者具有完整 sudo 訪問權限的用戶身份登錄時,恢復 root 用戶密碼是一項微不足道的任務,但在管理員未登錄時,這項任務便略微有點復雜。在后面的情況中,管理員可以從 Live CD 中啟動,從其中掛載根文件系統并編輯 /etc/shadow。管理員還能夠在不使用外部介質的情況下執行根密碼恢復。
### 注意
在 Red Hat Enterprise Linux 6 及早期版本中,管理員可以從啟動系統進入 runlevel 1,然后看到一個 root 提示。在 Red Hat Enterprise Linux 7 計算機上與 runlevel 1 最接近的模擬是 rescue.target 和 emergency.target 目標,這兩個目標都需要 root 密碼才能登錄。
在 Red Hat Enterprise Linux 7 中,可以使從 initramfs 運行的腳本在某些點暫停,提供 root shell,然后在該 shell 存在的情況下繼續。雖然這主要是為了調試,但也可用于恢復丟失的 root 密碼:
1. 重新啟動系統。
2. 按任意鍵中斷啟動加載器倒計時。
3. 將光標移到需要啟動的條目。
4. 按 e 編輯選定的條目。
5. 將光標移到內核命令行(以 linux16 開頭的行)。
6. 附加 rd.break(就在從 initramfs 向實際系統移交控制權前,該操作會中斷)。
### 注意
initramfs 提示會顯示在內核命令行中指定為最后的任何控制臺中。
7. 按 Ctrl+x 使用這些更改進行啟動。
此時,會顯示 root Shell,且實際系統的 root 文件系統會在 /sysroot 中以只讀方式掛載。
### 重要
由于此時尚未啟用 SELinux,因此任何創建的新文件都不會分配有 SELinux 上下文。請記住,有些工具(例如 passwd)首先會創建一個文件,然后移動新文件以代替要編輯的文件,從而有效地創建不帶 SELinux 上下文的新文件。
此時要恢復 root 密碼,請使用以下步驟:
1. 以讀寫形式重新掛載 /sysroot。
~~~
switch_root:/# mount -oremount,rw /sysroot
~~~
2. 切換為 chroot 存放位置,其中 /sysroot 被視為文件系統樹的 root。
~~~
switch_root:/# chroot /sysroot
~~~
3. 設置 root 密碼:
~~~
sh-4.2# passwd root
~~~
4. 確保所有未標記的文件(包括此時的 /etc/shadow)在啟動過程中都會重新獲得標記。
~~~
sh-4.2# touch /.autorelabel
~~~
5. 鍵入 exit 兩次。第一次將退出 chroot 存放位置,第二次將退出 initramfs 調試 shell。
此時,系統將繼續啟動,執行完整的 SELinux 重新標記,然后再次重新啟動。
## 診斷和修復 systemd 啟動問題
如果在啟動服務過程中出現問題,則有幾個工具可供系統管理員用于協助調試和/或故障排除:
早期調試 shell
通過運行 systemctl enable debug-Shell.service,啟動序列早期將在 TTY9(Ctrl+Alt+9)上生成一個 root Shell。該 Shell 會自動作為 root 登錄,這樣,管理員可以在系統仍在啟動時使用一些其他調試工具。
### 警告
在完成調試后,請不要忘記禁用 debug-shell.service 服務,因為該服務會使未經身份驗證的 root shell 向任何擁有本地控制臺訪問權限的人開放。
#### 緊急情況和救援目標
通過從啟動加載器將 systemd.unit=rescue.target 或 systemd.unit=emergency.target 附加到內核命令行,系統將生成特殊的救援或緊急情況 shell,而不是正常啟動。這兩個 shell 都需要提供 root 密碼。emergency 目標使 root 文件系統以只讀方式掛載,而 rescue.target 會等待 sysinit.target 先完成,這樣更多的系統會進行初始化,例如日志記錄,文件系統等。從這些 shell 退出后,系統會繼續進行常規啟動過程。
#### 阻塞作業
在啟動過程中,systemd 會生成大量作業。如果其中某些作業無法完成,則它們會防礙其他作業運行。要檢查當前作業列表,管理員可以使用命令 systemctl list-jobs。所有列為 running的作業都必須完成,然后列為 waiting 的作業才可以繼續。
### 參考
systemd.target、systemd.special、sulogin、sushell 和 systemctl man page
/usr/lib/systemd/system/debug-shell.service