15 systemd
精靈 #
systemd
負責啟始化系統,它的程序 ID 為 1。systemd
由核心直接啟動,訊號 9 (通常會終止程序) 對它不起作用。所有其他程式或由 systemd
直接啟動,或由它的其中一個子程序啟動。systemd
取代了 System V init 精靈,並且透過支援 init 程序檔與 System V init 完全相容。
systemd
的主要優點是透過平行化服務啟動,大大加快了開機速度。另外,systemd
僅在確實需要服務時才會啟動該服務。即不會在開機時無條件啟動精靈,而是在第一次需要時才會啟動。systemd
還支援核心控制群組 (cgroup)、建立快照和還原系統狀態。如需詳細資訊,請造訪 http://www.freedesktop.org/wiki/Software/systemd/。
15.1 systemd
概念 #
以下幾節介紹 systemd
背後的概念。
systemd
是適用於 Linux 的系統和工作階段管理員,它與 System V 及 LSB init 程序檔相容。systemd
的主要功能包括:
平行化能力
使用通訊端和 D-Bus 啟用來啟動服務
依需求啟動精靈
使用 Linux cgroup 追蹤程序
建立快照和還原系統狀態
維護掛接點和自動掛接點
實作事務相關型複雜的服務控制邏輯
15.1.1 單位檔案 #
單位組態檔案包含有關以下項目的資訊:服務、通訊端、裝置、掛接點、自動掛接點、交換檔案或分割區、啟動目標、監控的檔案系統路徑、受 systemd
控制和監督的計時器、暫時系統狀態快照、資源管理片段,或一組外部建立的程序。
「單位檔案」是 systemd
用於表示下列項目的通用術語:
服務: 程序相關資訊 (例如執行精靈);檔案名以 .service 結尾
目標: 用於將單位分組以及在啟動期間用作同步點;檔案名以 .target 結尾
插槽: IPC 或網路插槽或檔案系統 FIFO 的相關資訊,適用於插槽型啟動 (如
inetd
);檔案名以 .socket 結尾路徑: 用於觸發其他單位 (例如,在檔案變更時執行服務);檔案名以 .path 結尾
計時器: 受控計時器的相關資訊,適用於計時器型啟動;檔案名以 .timer 結尾
掛接點: 通常由 fstab 產生器自動產生;檔案名以 .mount 結尾
自動掛接點: 檔案系統自動掛接點的相關資訊;檔案名以 .automount 結尾
Swap: 用於記憶體分頁之交換裝置或檔案相關資訊;檔案名以 .swap 結尾
裝置: sysfs/udev(7) 裝置樹中所展示之裝置的相關資訊;檔案名以 .automount 結尾
範圍/片段: 分階層管理程序群組之資源的概念;檔案名以 .scope/.slice 結尾
如需 systemd
單位檔案的詳細資訊,請參閱 http://www.freedesktop.org/software/systemd/man/systemd.unit.html
15.2 基本用法 #
System V init 系統使用若干個指令來處理服務 - init 程序檔、insserv
、telinit
及其他。systemd
可簡化服務管理,因為對於大部分處理服務的任務,只需記住一條指令:systemctl
。它使用「
指令加子指令」表示法,與 git
或 zypper
相似:
systemctl GENERAL OPTIONS SUBCOMMAND SUBCOMMAND OPTIONS
如需完整的手冊,請參閱 man 1 systemctl
。
如果輸出進入終端機 (而不是進入管線或檔案之類),systemd
指令依預設會將長輸出傳送到頁面巡覽區。使用 --no-pager
選項可關閉切換模式。
systemd
還支援 bash 補齊,允許您輸入子指令的頭幾個字母,然後按 →|。此功能僅可用於 bash
外圍程序,並且需要安裝套件 bash-completion
。
15.2.1 管理正在執行系統中的服務 #
用於管理服務的子指令與透過 System V init 管理服務的子指令相同 (start
、stop
、...)。下面列出了服務管理指令的通用語法:
systemd
systemctl reload|restart|start|status|stop|... MY_SERVICE(S)
- System V init
rcMY_SERVICE(S) reload|restart|start|status|stop|...
systemd
可讓您一次管理多個服務。它不是像 System V init 那樣依次執行 init 程序檔,而是執行類似如下的指令:
tux >
sudo
systemctl start MY_1ST_SERVICE MY_2ND_SERVICE
若要列出系統上所有可用的服務:
tux >
sudo
systemctl list-unit-files --type=service
下表列出了 systemd
和 System V init 最重要的服務管理指令:
任務 |
|
System V init 指令 |
---|---|---|
啟動: |
start |
start |
停止: |
stop |
stop |
重新啟動: 關閉服務,然後啟動這些服務。如果某項服務並未執行,則會將其啟動。 |
restart |
restart |
有條件地重新啟動: 如果服務目前正在執行中,則予以重新啟動。對於未在執行中的服務,則不執行任何動作。 |
try-restart |
try-restart |
重新載入:
指示服務重新載入它們的組態檔案,而不中斷操作。使用案例:指示 Apache 重新載入修改過的 |
reload |
reload |
重新載入或重新啟動: 如果服務支援重新載入,則重新載入服務,否則重新啟動服務。如果某項服務並未執行,則會將其啟動。 |
reload-or-restart |
n/a |
有條件地重新載入或重新啟動: 如果服務支援重新載入,則重新載入服務,否則重新啟動那些目前正在執行的服務。對於未在執行中的服務,則不執行任何動作。 |
reload-or-try-restart |
n/a |
取得詳細的狀態資訊:
列出服務狀態的相關資訊。 |
status |
status |
取得簡要的狀態資訊: 顯示服務是否處於使用中狀態。 |
is-active |
status |
15.2.2 永久啟用/停用服務 #
上一節中提及的服務管理指令可讓您操作目前工作階段的服務。systemd
還可讓您永久啟用或停用服務,使之可以按要求自動啟動,或者始終無法使用。此操作可以透過 YaST 或在指令行上執行。
15.2.2.1 在指令行上啟用/停用服務 #
下表列出了 systemd
和 System V init 用於啟用和停用服務的指令:
在指令行上啟用服務時,服務不會自動啟動。系統將其排定為下一次系統啟動或執行層級/目標變更時啟動。若要在啟用服務之後立即啟動它,請明確執行 systemctl start MY_SERVICE
或 rc MY_SERVICE start
。
任務 |
|
System V init 指令 |
---|---|---|
啟用: |
|
|
停用: |
|
|
檢查: 顯示是否已啟用某個服務。 |
|
|
重新啟用: 與重新啟動服務相似,此指令先停用服務,然後再啟用該服務。若要使用服務的預設值重新啟用服務,可使用此任務。 |
|
無 |
遮罩: 「 停用」某項服務之後,仍然可以手動啟動它。若要徹底停用服務,您需要予以遮罩。使用須謹慎。 |
|
無 |
取消遮罩: 遮罩某項服務之後,惟有先將其取消遮罩,才能再次予以使用。 |
|
無 |
15.3 系統啟動和目標管理 #
啟動和關閉系統的整個程序由 systemd
維護。依此觀點,核心可以視為背景程序,以維護所有其他程序,並根據其他程式的要求來調整 CPU 時間和硬體存取。
15.3.1 目標與執行層級的比較 #
使用 System V init 時,系統將開機進入「
執行層級」。執行層級定義了系統的啟動方式,以及在所執行的系統中可以使用哪些服務。執行層級標有編號;最常見的執行層級是 0
(關閉系統)、3
(多重使用者,包含網路) 和 5
(多重使用者,包含網路及顯示管理員)。
systemd
使用所謂的「目標單位」引入新的概念。不過,它仍然與執行層級概念完全相容。目標單位是有名稱而不是有編號的,它有多個作用。例如,目標 local-fs.target
和 swap.target
掛接本地檔案系統和交換空間。
目標 graphical.target
提供包含網路和顯示管理員功能的多重使用者系統,與執行層級 5 相當。複雜的目標,例如 graphical.target
透過結合其他目標的子集用作「
中繼」目標。因為 systemd
能夠組合現有目標,便於建立自訂目標,因此提供了極大的靈活性。
下列清單顯示了最重要的 systemd
目標單位。如需完整清單,請參閱 man 7 systemd.special
。
systemd
目標單位 #default.target
預設開機的目標。這並非「 真實」目標,而是一個符號連結,指向
graphic.target
之類的另一個目標。可透過 YaST 永久變更 (請參閱第 15.4 節 「使用 YaST 管理服務」)。若要為某個工作階段變更它,請在開機提示處使用核心參數systemd.unit=MY_TARGET.target
。emergency.target
在主控台上啟動緊急外圍程序。請僅在開機提示符處以如下格式使用它:
systemd.unit=emergency.target
。graphical.target
啟動包含網路、多重使用者支援和顯示管理員功能的系統。
halt.target
關閉系統。
mail-transfer-agent.target
啟動傳送和接收郵件所需的所有服務。
multi-user.target
啟動包含網路的多重使用者系統。
reboot.target
系統重新開機。
rescue.target
啟動不包含網路的單一使用者系統。
為了保持與 System V init 執行層級系統的相容,systemd
提供了名為 runlevelX.target
的特殊目標,對應於編號為 X 的相應執行層級。
如果您要知道目前的目標,請使用指令:systemctl get-default
System V 執行層級 |
|
用途 |
---|---|---|
0 |
|
關閉系統 |
1, S |
|
單一使用者模式 |
2 |
|
本地多重使用者,不包含遠端網路 |
3 |
|
完整的多重使用者,包含網路 |
4 |
|
未使用/使用者定義 |
5 |
|
完整的多重使用者,包含網路及顯示管理員 |
6 |
|
系統重新開機 |
systemd
會忽略 /etc/inittab
System V init 系統中的執行層級在 /etc/inittab
中設定。systemd 不使用此組態。如需如何建立您自己的可開機目標的指示,請參閱第 15.5.4 節 「建立自訂目標」。
15.3.1.1 用於變更目標的指令 #
請使用下列指令來操作目標單位:
任務 |
|
System V init 指令 |
---|---|---|
變更目前的目標/執行層級 |
|
|
變更為預設目標/執行層級 |
|
無 |
取得目前的目標/執行層級 |
對於 |
或
|
永久性變更預設的執行層級 |
使用服務管理員或執行下列指令:
|
使用服務管理員或變更以下行
(位於 |
變更目前開機程序的預設執行層級 |
在開機提示的選項中輸入下列文字:
|
在開機提示中輸入所需的執行層級編號。 |
顯示目標/執行層級的相依性 |
「Requires」 會列出硬相依性 (必須解析的相依性),而 「Wants」 則列出軟相依性 (可行時解析的相依性)。 |
無 |
15.3.2 系統啟動除錯 #
systemd
針對系統啟動過程提供了分析方法。您可以查看所有服務及其狀態的清單 (而不必剖析 /var/log/
)。systemd
還允許您掃描啟動程序,以瞭解每項服務耗費多長時間啟動。
15.3.2.1 檢視服務的啟動情況 #
若要檢閱自從系統開機以來已啟動的完整服務清單,請輸入指令 systemctl
。這將列出所有使用中的服務,如下方所述 (已縮短)。若要獲得特定服務的詳細資訊,請使用 systemctl status MY_SERVICE
。
root #
systemctl
UNIT LOAD ACTIVE SUB JOB DESCRIPTION
[...]
iscsi.service loaded active exited Login and scanning of iSC+
kmod-static-nodes.service loaded active exited Create list of required s+
libvirtd.service loaded active running Virtualization daemon
nscd.service loaded active running Name Service Cache Daemon
chronyd.service loaded active running NTP Server Daemon
polkit.service loaded active running Authorization Manager
postfix.service loaded active running Postfix Mail Transport Ag+
rc-local.service loaded active exited /etc/init.d/boot.local Co+
rsyslog.service loaded active running System Logging Service
[...]
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.
161 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
若要限制為輸出無法啟動的服務,請使用 --failed
選項:
root #
systemctl --failed
UNIT LOAD ACTIVE SUB JOB DESCRIPTION
apache2.service loaded failed failed apache
NetworkManager.service loaded failed failed Network Manager
plymouth-start.service loaded failed failed Show Plymouth Boot Screen
[...]
15.3.2.2 啟動時間除錯 #
為了對系統啟動時間除錯,systemd
提供了 systemd-analyze
指令。它會顯示總啟動時間以及按啟動時間排序的服務清單,還可以產生 SVG 圖,其中顯示各服務相對於其他服務所耗費的啟動時間。
- 列出系統啟動時間
root #
systemd-analyze Startup finished in 2666ms (kernel) + 21961ms (userspace) = 24628ms- 列出服務啟動時間
root #
systemd-analyze blame 15.000s backup-rpmdb.service 14.879s mandb.service 7.646s backup-sysconfig.service 4.940s postfix.service 4.921s logrotate.service 4.640s libvirtd.service 4.519s display-manager.service 3.921s btrfsmaintenance-refresh.service 3.466s lvm2-monitor.service 2.774s plymouth-quit-wait.service 2.591s firewalld.service 2.137s initrd-switch-root.service 1.954s ModemManager.service 1.528s rsyslog.service 1.378s apparmor.service [...]- 服務啟動時間圖
root #
systemd-analyze plot > jupiter.example.com-startup.svg
15.3.2.3 檢視完整的啟動程序 #
上面的指令行出了已啟動的服務及其啟動時間。如需更詳細的綜覽,請在開機提示符處指定以下參數,以指示 systemd
建立完整啟動程序的詳細記錄。
systemd.log_level=debug systemd.log_target=kmsg
現在,systemd
會將記錄訊息寫入核心環緩衝區。該緩衝區可透過 dmesg
檢視:
tux >
dmesg -T | less
15.3.3 System V 相容性 #
Systemd
與 System V 相容,因此,您仍可以使用現有的 System V init 程序檔。但是,至少有一個已知問題會導致 System V init 程序檔不能立即與 systemd
配合使用:透過 init 程序檔中的 su
或 sudo
以其他使用者身分啟動服務會導致程序檔失敗,產生「拒絕存取」錯誤。
使用 su
或 sudo
變更使用者時,會啟動 PAM 工作階段。完成 init 程序檔後會終止此工作階段。因此,init 程序檔啟動的服務也會終止。若要解決此問題,請執行下列步驟:
建立與 init 程序檔同名、副檔名為
.service
的服務檔案包裝程式。[Unit] Description=DESCRIPTION After=network.target [Service] User=USER Type=forking1 PIDFile=PATH TO PID FILE1 ExecStart=PATH TO INIT SCRIPT start ExecStop=PATH TO INIT SCRIPT stop ExecStopPost=/usr/bin/rm -f PATH TO PID FILE1 [Install] WantedBy=multi-user.target2
以適當的值取代 UPPERCASE LETTERS 中寫入的所有值。
使用
systemctl start 應用程式
啟動精靈。
15.4 使用 YaST 管理服務 #
基本服務管理也可以透過 YaST 服務管理員模組實現。該模組不僅支援啟動、停止、啟用和停用服務,還可用於顯示服務的狀態以及變更預設目標。若要啟動 YaST 模組,請選取「
› › 」。- 變更
若要變更系統開機進入的目標,請從
下拉方塊中選擇目標。最常用的目標是 (啟動圖形登入畫面) 和 (以指令行模式啟動系統)。- 啟動或停止服務
從表中選取服務。
欄顯示它目前是正在執行 ( ) 還是未在執行 ( )。透過選擇 或 可切換其狀態。如果啟動或停止服務,會變更其對目前執行中工作階段而言的狀態。若要在整個重新開機期間變更服務的狀態,您需要啟用或停用服務。
- 定義服務啟動行為
服務可以在開機時自動啟動,也可以手動啟動。從表中選取服務。
欄顯示它目前是 啟動還是 啟動。透過選擇 可切換其狀態。若要在目前工作階段中變更服務狀態,您需要依據上述方式啟動或停止服務。
- 檢視狀態訊息
若要檢視服務的狀態訊息,請從清單中選取該服務,然後選擇
。您看到的輸出與systemctl
-l
status MY_SERVICE 指令產生的輸出完全相同。
15.5 自訂 systemd
#
下列各節列出了 systemd
自訂的一些範例。
在自訂 systemd
時,請務必使用目錄 /etc/systemd/
,切勿使用 /usr/lib/systemd/
。否則,systemd
下次更新時會覆寫您的變更。
15.5.1 自訂單位檔案 #
建議使用 systemctl edit SERVICE
指令來自訂單位檔案。此指令會啟動預設的文字編輯器,並建立一個在 /etc/systemd/system/NAME.service.d/
中包含 override.conf
檔案的目錄。該指令還確定會向正在執行的 systemd
程序通知這些變更。
或者,您可以透過執行 systemctl edit --full SERVICE
來開啟原始檔案的副本進行編輯,而不是開啟一個空白檔案。編輯檔案時,請確定未移除任何現有區段。
下面將練習如何變更系統等待 MariaDB 啟動的時間。以 root 身分執行 systemctl edit --full mariadb.service
。開啟的檔案如下所示:
[Unit] Description=MySQL server Wants=basic.target Conflicts=mariadb.target After=basic.target network.target [Install] WantedBy=multi-user.target Alias=mysql.service [Service] Restart=on-abort Type=notify ExecStartPre=/usr/lib/mysql/mysql-systemd-helper install ExecStartPre=/usr/lib/mysql/mysql-systemd-helper upgrade ExecStart=/usr/lib/mysql/mysql-systemd-helper start # Configures the time to wait for start-up/stop TimeoutSec=300 # Prevent writes to /usr, /boot, and /etc ProtectSystem=full # Prevent accessing /home, /root and /run/user ProtectHome=true UMask=007
調整 TimeoutSec
值並儲存變更。若要啟用變更,請以 root 身分執行 systemctl daemon-reload
。
如需詳細資訊,請參閱可使用 man 1 systemctl
指令呼叫的 man 頁面。
15.5.2 建立放入式檔案 #
若要對組態檔案進行微小變更,請使用所謂的放入式檔案。放入式檔案可讓您延伸單位檔案的組態,而不必編輯或覆寫單位檔案本身。
例如,若要變更位於 /usr/lib/systemd/system/FOOBAR.SERVICE
中 FOOBAR 服務的單個值,請依照以下步驟操作:
建立名為
/etc/systemd/system/FOOBAR.service.d/
的目錄。注意字尾為
.d
。該目錄必須命名為要透過所放入之檔案修補的服務。在該目錄中,建立
your_modification.conf
檔案。確保該檔案僅包含待修改值所在的行。
將您所做的變更儲存到檔案中。
為避免放入式檔案與 SUSE 隨附檔案之間出現名稱衝突,建議在所有放入式檔案名稱前加上一個兩位數和一個破折號:例如,80-override.conf
。
以下範圍為保留值範圍:
0-19
,為systemd
上游保留20-25
,為 SUSE 隨附的systemd
保留26-29
,為 SUSE 套件 (systemd 除外) 保留50
,為使用systemctl set-property
建立的放入式檔案保留
請使用大於此範圍的兩位數,以確定 SUSE 隨附的任何放入式檔案都不會覆寫您自己的放入式檔案。
您可以使用 systemctl cat $UNIT
來列出並驗證考慮將哪些檔案納入單位組態。
15.5.3 將 xinetd
服務轉換為 systemd
#
從 SUSE Linux Enterprise Server 15 版本開始,移除了 xinetd
基礎架構。本節概述如何將現有的自訂 xinetd
服務檔案轉換為 systemd
通訊端。
對於每個 xinetd
服務檔案,您至少需要兩個 systemd
單位檔案:通訊端檔案 (*.socket
) 和關聯的服務檔案 (*.service
)。通訊端檔案告訴 systemd
要建立哪個通訊端,服務檔案告訴 systemd
要啟動哪個可執行檔。
以下面的 xinetd
服務檔案為例:
root #
cat /etc/xinetd.d/example
service example
{
socket_type = stream
protocol = tcp
port = 10085
wait = no
user = user
group = users
groups = yes
server = /usr/libexec/example/exampled
server_args = -auth=bsdtcp exampledump
disable = no
}
若要將它轉換為 systemd
,需要下面兩個相配的檔案:
root #
cat /usr/lib/systemd/system/example.socket
[Socket]
ListenStream=0.0.0.0:10085
Accept=false
[Install]
WantedBy=sockets.target
root #
cat /usr/lib/systemd/system/example.service
[Unit]
Description=example
[Service]
ExecStart=/usr/libexec/example/exampled -auth=bsdtcp exampledump
User=user
Group=users
StandardInput=socket
如需 systemd
的「通訊端」和「服務」檔案選項的完整清單,請參閱 systemd.socket 和 systemd.service 手冊頁 (man 5 systemd.socket
、man 5 systemd.service
)。
15.5.4 建立自訂目標 #
在 System V init SUSE 系統上並未使用執行層級 4,便於管理員自行建立執行層級組態。systemd
可讓您建立任意個自訂目標。建議您在開始時先在 graphical.target
等現有的目標上調整。
將組態檔案
/usr/lib/systemd/system/graphical.target
複製到/etc/systemd/system/MY_TARGET.target
,並依據需要調整該檔案。上一步中複製的組態檔案已涵蓋該目標的必要的 (「 硬」) 相依性。若要一併納入需要的 (「軟」) 相依項,請建立目錄
/etc/systemd/system/MY_TARGET.target.wants
。對每個需要的服務,建立從
/usr/lib/systemd/system
連到/etc/systemd/system/MY_TARGET.target.wants
的符號連結。設定好目標後,重新載入
systemd
組態以使新目標可用:tux >
sudo
systemctl daemon-reload
15.6 進階用法 #
下列各節涵蓋進階主題,適用於系統管理員。如需更為進階的 systemd
文件,請參閱 Lennart Pöttering 撰寫的適用於管理員的 systemd
相關系列文章,網址為 http://0pointer.de/blog/projects。
15.6.1 清理暫存目錄 #
systemd
支援定期清理暫存目錄。將會自動移轉並啟用前一系統版本中的組態。tmpfiles.d
(負責管理暫存檔案) 將從 /etc/tmpfiles.d/*.conf
、/run/tmpfiles.d/*.conf
和 /usr/lib/tmpfiles.d/*.conf
檔案中讀取其組態。/etc/tmpfiles.d/*.conf
中的組態將會覆寫其他兩個目錄中的相關組態 (/usr/lib/tmpfiles.d/*.conf
是套件將其組態檔案儲存到的位置)。
組態格式為每個路徑一行,該行包含動作與路徑、(選擇性) 模式、擁有權、期限和引數欄位,具體視動作而定。以下範例將取消連結 X11 鎖定檔案:
Type Path Mode UID GID Age Argument r /tmp/.X[0-9]*-lock
若要取得 tmpfile 計時器的狀態:
tux >
sudo
systemctl status systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.timer - Daily Cleanup of Temporary Directories Loaded: loaded (/usr/lib/systemd/system/systemd-tmpfiles-clean.timer; static) Active: active (waiting) since Tue 2018-04-09 15:30:36 CEST; 1 weeks 6 days ago Docs: man:tmpfiles.d(5) man:systemd-tmpfiles(8) Apr 09 15:30:36 jupiter systemd[1]: Starting Daily Cleanup of Temporary Directories. Apr 09 15:30:36 jupiter systemd[1]: Started Daily Cleanup of Temporary Directories.
如需處理暫存檔案的詳細資訊,請參閱 man 5 tmpfiles.d
。
15.6.2 系統記錄 #
第 15.6.9 節 「服務除錯」說明如何檢視給定服務的記錄訊息。然而,記錄的訊息顯示並不局限為服務記錄。您還可以存取和查詢 systemd
寫入的完整記錄訊息 — 亦即「日誌」。使用 journalctl
指令可顯示從最舊項目開始的完整記錄訊息。如需套用過濾器或變更輸出格式等選項的資訊,請參閱 man 1 journalctl
。
15.6.3 快照 #
您可以使用 isolate
子指令將 systemd
的目前狀態儲存到指定的快照,日後可以回復到該狀態。此功能在測試服務或自訂目標時非常有用,因為它允許您隨時回到定義的狀態。快照僅在目前工作階段中可用,重新開機時將自動刪除。快照名稱必須以 .snapshot
結尾。
- 建立快照
tux >
sudo
systemctl snapshot MY_SNAPSHOT.snapshot- 刪除快照
tux >
sudo
systemctl delete MY_SNAPSHOT.snapshot- 檢視快照
tux >
sudo
systemctl show MY_SNAPSHOT.snapshot- 啟用快照
tux >
sudo
systemctl isolate MY_SNAPSHOT.snapshot
15.6.4 載入核心模組 #
使用 systemd
,可透過 /etc/modules-load.d
中的組態檔案,在開機時自動載入核心模組。該檔案應命名為 MODULE.conf 並包含以下內容:
# load module MODULE at boot time MODULE
如果某個套件安裝了用於載入核心模組的組態檔案,該檔案將安裝到 /usr/lib/modules-load.d
。如果存在兩個同名的組態檔案,將優先使用 /etc/modules-load.d
中的組態檔案。
如需詳細資訊,請參閱 modules-load.d(5)
線上文件。
15.6.5 載入服務之前執行動作 #
使用 System V 時,需要在載入服務之前執行的 init 動作必須在 /etc/init.d/before.local
中指定。systemd
不再支援此程序。如果您需要在啟動服務之前執行動作,請執行以下步驟:
- 載入核心模組
在
/etc/modules-load.d
目錄中建立一個 drop-in 檔案 (如需語法,請參閱man modules-load.d
)- 建立檔案或目錄,清理目錄,變更擁有權
在
/etc/tmpfiles.d
中建立一個 drop-in 檔案 (如需語法,請參閱man tmpfiles.d
)- 其他任務
從以下範本建立一個系統服務檔案,例如
/etc/systemd/system/before.service
:[Unit] Before=NAME OF THE SERVICE YOU WANT THIS SERVICE TO BE STARTED BEFORE [Service] Type=oneshot RemainAfterExit=true ExecStart=YOUR_COMMAND # beware, executable is run directly, not through a shell, check the man pages # systemd.service and systemd.unit for full syntax [Install] # target in which to start the service WantedBy=multi-user.target #WantedBy=graphical.target
建立服務檔案後,應執行以下指令 (以
root
身分):tux >
sudo
systemctl daemon-reloadtux >
sudo
systemctl enable before每次修改服務檔案時,都需要執行:
tux >
sudo
systemctl daemon-reload
15.6.6 核心控制群組 (cgroup) #
在傳統 System V init 系統上不一定能將程序明確指派給繁衍它的服務。有些服務 (例如 Apache) 會繁衍許多協力廠商程序 (例如 CGI 或 Java 程序),這些程序本身又會繁衍許多程序。這導致您很難明確指派,甚至根本無法明確指派。另外,服務在不當終止後,可能殘留部分子項保持活動狀態。
systemd
將每個服務放入它自己的 cgroup 中,從而解決此問題。cgroup 是一項核心功能,允許將程序及其所有子程序聚合至分層組織的群組中。systemd
根據相應的服務為每個 cgroup 命名。由於程序未經特許不得「離開」其 cgroup,因此這樣可以有效地使用服務名稱標記該服務繁衍的所有程序。
若要列出屬於服務的所有程序,請使用指令 systemd-cgls
。結果類似於以下範例 (已縮短):
root #
systemd-cgls --no-pager
├─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 20
├─user.slice
│ └─user-1000.slice
│ ├─session-102.scope
│ │ ├─12426 gdm-session-worker [pam/gdm-password]
│ │ ├─15831 gdm-session-worker [pam/gdm-password]
│ │ ├─15839 gdm-session-worker [pam/gdm-password]
│ │ ├─15858 /usr/lib/gnome-terminal-server
[...]
└─system.slice
├─systemd-hostnamed.service
│ └─17616 /usr/lib/systemd/systemd-hostnamed
├─cron.service
│ └─1689 /usr/sbin/cron -n
├─postfix.service
│ ├─ 1676 /usr/lib/postfix/master -w
│ ├─ 1679 qmgr -l -t fifo -u
│ └─15590 pickup -l -t fifo -u
├─sshd.service
│ └─1436 /usr/sbin/sshd -D
[...]
如需 cgroup 的詳細資訊,請參閱Chapter 9, Kernel control groups。
15.6.7 終止服務 (傳送訊號) #
如第 15.6.6 節 「核心控制群組 (cgroup)」中所述,在 System V init 系統中不一定能將程序指派給其父服務,導致難以終止服務及其所有子項。未終止的子程序將保留為廢止程序。
systemd
的概念是將每個服務限制在某個 cgroup 中,從而可以明確識別一個服務的所有子程序,因此可讓您將訊號傳送給這些程序中的每個程序。可使用 systemctl kill
將信號傳送給服務。如需可用信號清單,請參閱 man 7 signals
。
- 將
SIGTERM
傳送給服務 SIGTERM
是傳送的預設信號。tux >
sudo
systemctl kill MY_SERVICE- 將 SIGNAL 傳送給服務
可使用
-s
選項指定應傳送的信號。tux >
sudo
systemctl kill -s SIGNAL MY_SERVICE- 選取程序
依預設,
kill
指令會將信號傳送給指定 cgroup 的all
程序。您可以將傳送目標限制為control
或main
程序。後者非常實用,如下例透過傳送SIGHUP
強制服務重新載入其組態所示:tux >
sudo
systemctl kill -s SIGHUP --kill-who=main MY_SERVICE
15.6.8 有關 D-Bus 服務的重要說明 #
D-Bus 服務是 systemd
用戶端與做為 pid 1 執行的 systemd 管理員之間進行通訊的訊息匯流排。雖然 dbus
是個獨立的精靈,但它也是 init 基礎架構的組成部分。
在執行中的系統中終止或重新啟動 dbus
的效果類似於嘗試終止或重新啟動 pid 1。此操作將中斷 systemd
用戶端與伺服器間的通訊,並使大部分 systemd
功能不可用。
因此,不建議也不支援終止或重新啟動 dbus
。
更新 dbus
或與 dbus
有關的套件需要重新開機。如果不確定是否需要重新開機,請執行 sudo zypper ps -s
。如果 dbus
顯示在所列服務之中,則表明您需要將系統重新開機。
請記住,即使自動更新設定為跳過需要重新開機的套件,dbus
仍會更新。
15.6.9 服務除錯 #
依預設,systemd
的輸出不會太詳細。如果服務啟動成功,則不會產生任何輸出。如果啟動失敗,則會顯示簡短的錯誤訊息。不過,systemctl status
可讓您以不同方式對服務的啟動和作業進行除錯。
systemd
隨附自己的記錄機製 (「日誌」),可以記錄系統訊息,便於您一併顯示服務訊息與狀態訊息。status
指令的工作方式與 tail
相似,也可以採用不同的格式顯示記錄訊息,因此成為功能強大的除錯工具。
- 顯示服務啟動失敗訊息
每當服務啟動失敗時,使用
systemctl status MY_SERVICE
可獲得詳細的錯誤訊息:root #
systemctl start apache2 Job failed. See system journal and 'systemctl status' for details.root #
systemctl status apache2 Loaded: loaded (/usr/lib/systemd/system/apache2.service; disabled) Active: failed (Result: exit-code) since Mon, 04 Apr 2018 16:52:26 +0200; 29s ago Process: 3088 ExecStart=/usr/sbin/start_apache2 -D SYSTEMD -k start (code=exited, status=1/FAILURE) CGroup: name=systemd:/system/apache2.service Apr 04 16:52:26 g144 start_apache2[3088]: httpd2-prefork: Syntax error on line 205 of /etc/apache2/httpd.conf: Syntax error on li...alHost>- 顯示最後 N 條服務訊息
status
子指令的預設行為是顯示服務發出的最近 10 條訊息。若要變更要顯示的訊息數,請使用--lines=N
參數:tux >
sudo
systemctl status chronydtux >
sudo
systemctl --lines=20 status chronyd- 以附加模式顯示服務訊息
若要顯示服務訊息的「 即時串流」,請使用
--follow
選項,其工作方式與tail
-f
相似:tux >
sudo
systemctl --follow status chronyd- 訊息輸出格式
--output=模式
參數可讓您變更服務訊息的輸出格式。最重要的可用模式如下:short
預設格式。顯示記錄訊息及易於理解的時戳。
verbose
完整輸出所有欄位。
cat
精簡輸出,不含時戳。
15.7 systemd
計時器單位 #
與 cron 類似,systemd
計時器單位提供了一種在 Linux 上排程工作的機制。雖然 systemd
計時器單位的用途與 cron 相同,但其具備幾項優點。
使用計時器單位排程的工作可以依賴於其他
systemd
服務。計時器單位被視為一般
systemd
服務,因此可以使用systemctl
進行管理。計時器可以是即時計時器,也可以是單純計時器。
時間單位會被記錄到
systemd
日誌中,使得更易於監控和疑難排解。
systemd
計時器單位透過 .timer
副檔名識別。
15.7.1 systemd
計時器類型 #
計時器單位可以使用單純計時器和即時計時器。
與 cron 工作類似,即時計時器是依據行事曆事件觸發的。即時計時器使用選項
OnCalendar
進行定義。單純計時器將從某個特定起點開始經過指定時間後觸發。後者可以是系統開機或系統單位啟用事件。有幾個選項可用於定義單純計時器,包括
OnBootSec
、OnUnitActiveSec
和OnTypeSec
。單純計時器不是永久的,每次重新開機後都將被重設。
15.7.2 systemd
計時器和服務單位 #
每個計時器單位都必須有一個其所控制的相應 systemd
單位檔案。也就是說,將由 .timer
檔案啟用並管理相應的 .service
檔案。使用計時器時,.service
檔案不需要 [Install]
區段,因為服務將由計時器管理。
15.7.3 具體範例 #
為了理解 systemd
計時器單位的基本知識,我們設定了一個觸發 foo.sh
外圍程序程序檔的計時器。
第一步是建立用於控制外圍程序程序檔的 systemd
服務單位。為此,請開啟一個新的文字檔案進行編輯,並新增以下服務單位定義:
[Unit] Description="Foo shell script" [Service] ExecStart=/usr/local/bin/foo.sh
將檔案以名稱 foo.service
儲存到目錄 /etc/systemd/system/
中。
接下來,開啟一個新的文字檔案進行編輯,並新增以下計時器定義:
[Unit] Description="Run foo shell script" [Timer] OnBootSec=5min OnUnitActiveSec=24h Unit=foo.service [Install] WantedBy=multi-user.target
上述範例中的 [Timer]
區段指定了要觸發的服務 (foo.service
) 以及觸發時間。在此範例中,選項 OnBootSec
指定了一個在系統開機後五分鐘觸發服務的單純計時器,而選項 OnUnitActiveSec
會在服務被啟用後 24 小時觸發服務 (即計時器將每天觸發一次服務)。最後,選項 WantedBy
指定應在系統達到多使用者目標時啟動計時器。
您也可以不指定單純計時器,而是使用選項 OnCalendar
指定即時計時器。下面的即時計時器定義從星期一 12:00 開始,每週觸發一次相關服務單位。
[Timer] OnCalendar=weekly Persistent=true
選項 Persistent=true
表示如果計時器錯過了上一次啟動時間 (例如,由於系統關閉),則會在計時器啟用後立即觸發服務。
選項 OnCalendar
還可以用於使用以下格式來定義觸發服務的具體日期和時間:DayOfWeek Year-Month-Day Hour:Minute:Second
。下面的範例會在每天早上 5 點觸發服務:
OnCalendar=*-*-* 5:00:00
您可以使用星號指定任何值,使用逗號列出可能的值。使用由 .. 分隔的兩個值可表示一個連續的範圍。下面的範例會在每個月的星期五下午 6 點觸發服務:
OnCalendar=Fri *-*-1..7 18:00:00
若要在不同的時間觸發服務,您可以指定多個 OnCalendar
項目:
OnCalendar=Mon..Fri 10:00 OnCalendar=Sat,Sun 22:00
在上面的範例中,會在工作日的上午 10 點和週末的晚上 10 點觸發服務。
編輯好計時器單位檔案後,使用名稱 foo.timer
將其儲存到 /etc/systemd/system/
目錄中。若要檢查所建立的單位檔案是否正確,請執行以下指令:
tux >
sudo
systemd-analyze verify /etc/systemd/system/foo.*
如果指令未傳回任何輸出,則表示檔案成功通過驗證。
若要啟動計時器,請使用指令 sudo systemctl start foo.timer
。若要在開機時啟用計時器,請執行指令 sudo systemctl enable foo.timer
。
15.7.4 管理 systemd
計時器 #
由於計時器被視為一般 systemd
單位,因此您可以使用 systemctl
來管理它們。您可以使用 systemctl start
啟動計時器,使用 systemctl enable
啟用計時器,依此類推。除此之外,您還可以使用指令 systemctl list-timers
列出所有作用中計時器。若要列出包括非作用中計時器在內的所有計時器,請執行指令 systemctl list-timers --all
。
15.8 更多資訊 #
如需 systemd
的詳細資訊,請參閱以下線上資源:
- 首頁
- 適用於管理員的
systemd
Lennart Pöttering 是
systemd
的原著者之一,他撰寫了一系列部落格文章 (寫本章時已有 13 篇)。其網址為 http://0pointer.de/blog/projects。