systemd 是 Linux 下的一款系統和服務管理器,兼容 SysV 和 LSB 的啟動腳本。systemd 的特性有:支持並行化任務;同一時候採用 socket 式與 D-Bus 總線式激活服務;按需啟動守護進程(daemon)。利用 Linux 的 cgroups 監視進程;支持快照和系統恢復。維護掛載點和自己主動掛載點。各服務間基於依賴關系進行精密控制。
檢視和控制systemd的主要命令是systemctl。
該命令可用於查看系統狀態和管理系統及服務。詳見man 1 systemctl。
小貼士:
- 在 systemctl 參數中加入 -H <username>@<主機名> 能夠實現對其它機器的遠程控制。該過程使用 SSH連接。
- systemadm 是 systemd 的官方圖形前端。官方軟件倉庫 提供了穩定版本號 systemd-ui。
- Plasma 用戶能夠安裝 systemctl 圖形前端 systemd-kcm。安裝后能夠在 System administration 下找到
基本工具
分析系統狀態
顯示 系統狀態:
$ systemctl status
輸出激活的單元:
$ systemctl
下面命令等效:
$ systemctl list-units
輸出執行失敗的單元:
$ systemctl --failed
全部可用的單元文件存放在 /usr/lib/systemd/system/ 和 /etc/systemd/system/ 文件夾(后者優先級更高)。
查看全部已安裝服務:
$ systemctl list-unit-files
使用單元
一個單元配置文件能夠描寫敘述例如以下內容之中的一個:系統服務(.service)、掛載點(.mount)、sockets(.sockets) 、系統設備(.device)、交換分區(.swap)、文件路徑(.path)、啟動目標(.target)、由 systemd 管理的計時器(.timer)。
詳情參閱 man 5 systemd.unit。
使用 systemctl 控制單元時,通常須要使用單元文件的全名,包括擴展名(比如 sshd.service)。可是有些單元能夠在systemctl中使用簡寫方式。
- 假設無擴展名,systemctl 默認把擴展名當作 .service。
比如 netcfg 和 netcfg.service 是等價的。
- 掛載點會自己主動轉化為對應的 .mount 單元。比如 /home 等價於 home.mount。
- 設備會自己主動轉化為對應的 .device 單元,所以 /dev/sda2 等價於 dev-sda2.device。
Note: 有一些單元的名稱包括一個 @ 標記。 (e.g. name@string.service): 這意味着它是模板單元 name@.service 的一個 實例。 string 被稱作實例標識符, 在 systemctl 調用模板單元時,會將其當作一個參數傳給模板單元。模板單元會使用這個傳入的參數取代模板中的 %I 指示符。
在實例化之前。systemd 會先檢查 name@string.suffix 文件是否存在(假設存在,應該就是直接使用這個文件。而不是模板實例化了)。大多數情況下,包換 @ 標記都意味着這個文件是模板。假設一個模板單元沒有實例化就調用,該調用會返回失敗,由於模板單元中的 %I 指示符沒有被替換。
Tip:
下面的大部分命令都能夠跟多個單元名, 具體信息參見 man systemctl。
從systemd 220版本號開始, systemctl命令在enable、disable和mask子命令中添加了–now選項,能夠實現激活的同一時候啟動服務。取消激活的同一時候停止服務。
一個軟件包可能會提供多個不同的單元。假設你已經安裝了軟件包,能夠通過pacman -Qql package | grep systemd命令檢查這個軟件包提供了哪些單元。
馬上激活單元:
# systemctl start <單元>
馬上停止單元:
# systemctl stop <單元>
重新啟動單元:
# systemctl restart <單元>
又一次載入配置:
# systemctl reload <單元>
輸出單元執行狀態:
$ systemctl status <單元>
檢查單元是否配置為自己主動啟動:
$ systemctl is-enabled <單元>
開機自己主動激活單元:
# systemctl enable <單元>
取消開機自己主動激活單元:
# systemctl disable <單元>
禁用一個單元(禁用后,間接啟動也是不可能的):
# systemctl mask <單元>
取消禁用一個單元:
# systemctl unmask <單元>
顯示單元的手冊頁(必須由單元文件提供):
# systemctl help <單元>
又一次載入 systemd,掃描新的或有變動的單元:
# systemctl daemon-reload
電源管理
安裝 polkit 后才干夠一般用戶身份使用電源管理。
假設你正登錄在一個本地的systemd-logind用戶會話。且當前沒有其它活動的會話。那么下面命令無需root權限就可以執行。否則(比如。當前有還有一個用戶登錄在某個tty),systemd 將會自己主動請求輸入rootpassword。
重新啟動:
$ systemctl reboot
退出系統並停止電源:
$ systemctl poweroff
待機:
$ systemctl suspend
休眠:
$ systemctl hibernate
混合休眠模式(同一時候休眠到硬盤並待機):
$ systemctl hybrid-sleep
編寫單元文件
systemd 單元文件的語法來源於 XDG桌面入口配置文件.desktop文件。最初的源頭則是Microsoft Windows的.ini文件。
單元文件能夠從兩個地方載入。優先級從低到高各自是:
- /usr/lib/systemd/system/: 軟件包安裝的單元
- /etc/systemd/system/: 系統管理員安裝的單元
- 當systemd執行在用戶模式下時,使用的載入路徑是全然不同的。
- systemd 單元名僅能包括 ASCII 字符, 下划線和點號. 其它字符須要用 C-style “\x2d” 替換. 參閱 man systemd.unit 和 man systemd-escape.}}
單元文件的語法,能夠參考系統已經安裝的單元,也能夠參考man systemd.service中的EXAMPLES章節。
小貼士:
以 # 開頭的凝視可能也能用在 unit-files 中, 可是僅僅能在新行中使用。 不要在 systemd 的參數后面使用行末凝視, 否則 unit 將會啟動失敗。
處理依賴關系
使用systemd時,可通過正確編寫單元配置文件來解決其依賴關系。
典型的情況是,單元A要求單元B在A啟動之前執行。在此情況下。向單元A配置文件里的 [Unit] 段加入 Requires=B 和 After=B 就可以。若此依賴關系是可選的,可加入 Wants=B 和 After=B。請注意 Wants= 和 Requires= 並不意味着 After=,即假設 After= 選項沒有制定,這兩個單元將被並行啟動。
依賴關系通常被用在服務(service)而不是目標(target)上。比如, network.target 通常會被某個配置網絡接口的服務引入,所以,將自己定義的單元排在該服務之后就可以,由於 network.target 已經啟動。
服務類型
編寫自己定義的 service 文件時,能夠選擇幾種不同的服務啟動方式。啟動方式可通過配置文件 [Service] 段中的 Type= 參數進行設置。
- Type=simple(默認值):systemd覺得該服務將馬上啟動。服務進程不會fork。
假設該服務要啟動其它服務,不要使用此類型啟動。除非該服務是socket激活型。
- Type=forking:systemd覺得當該服務進程fork,且父進程退出后服務啟動成功。對於常規的守護進程(daemon),除非你確定此啟動方式無法滿足需求。使用此類型啟動就可以。使用此啟動類型應同一時候指定 PIDFile=,以便systemd能夠跟蹤服務的主進程。
- Type=oneshot:這一選項適用於僅僅執行一項任務、隨后馬上退出的服務。可能須要同一時候設置 RemainAfterExit=yes 使得 systemd 在服務進程退出之后仍然覺得服務處於激活狀態。
- Type=notify:與 Type=simple 相同,但約定服務會在就緒后向 systemd 發送一個信號。
這一通知的實現由 libsystemd-daemon.so 提供。
- Type=dbus:若以此方式啟動。當指定的 BusName 出如今DBus系統總線上時。systemd覺得服務就緒。
- Type=idle: systemd會等待全部任務處理完畢后。才開始執行idle類型的單元。
其它行為和Type=simple 相似。
type的很多其它解釋能夠參考 systemd.service(5)。
改動現存單元文件
為了避免和 pacman 沖突,不應該直接編輯軟件包提供的文件. 要更改由軟件包提供的單元文件,先創建名為 /etc/systemd/system/<單元名>.d/ 的文件夾(如 /etc/systemd/system/httpd.service.d/)。然后放入 *.conf 文件,當中能夠加入或重置參數。這里設置的參數優先級高於原來的單元文件。
比如。假設想加入一個額外的依賴。創建這么一個文件就可以:
-
/etc/systemd/system/ <unit>.d/customdependency.conf
-
[Unit]
-
Requires= <新依賴>
-
After= <新依賴>
As another example, in order to replace the ExecStart directive for a unit that is not of type oneshot, create the following file:
-
/etc/systemd/system/unit.d/customexec.conf
-
[
-
ExecStart=
-
ExecStart= new command
想知道為什么改動 ExecStart 前必須將其置空,參見 ([1]).
下面是自己主動重新啟動服務的一個樣例:
-
/etc/systemd/system/ unit.d/restart.conf
-
[Service]
-
Restart=always
-
RestartSec= 30
然后執行下面命令使更改生效:
此外,把舊的單元文件從 /usr/lib/systemd/system/ 拷貝到 /etc/systemd/system/,然后進行改動,也能夠達到相同效果。
在 /etc/systemd/system/ 文件夾中的單元文件的優先級總是高於 /usr/lib/systemd/system/ 文件夾中的同名單元文件。注意,當 /usr/lib/ 中的單元文件因軟件包升級變更時,/etc/ 中自己定義的單元文件不會同步更新。此外,你還得執行 systemctl reenable 。手動又一次啟用該單元。因此。建議使用前面一種利用 *.conf 的方法。
小貼士: 用 systemd-delta 命令來查看哪些單元文件被覆蓋、哪些被改動。
系統維護的時候須要及時了解哪些單元已經有了更新。
安裝 vim-systemd 軟件包,能夠使 unit 配置文件在 Vim 下支持語法高亮。
目標(target)
啟動級別(runlevel)是一個舊的概念。
如今,systemd 引入了一個和啟動級別功能相似又不同的概念——目標(target)。不像數字表示的啟動級別,每一個目標都有名字和獨特的功能,而且能同一時候啟用多個。一些目標繼承其它目標的服務,並啟動新服務。
systemd 提供了一些模仿 sysvinit 啟動級別的目標。仍能夠使用舊的 telinit 啟動級別 命令切換。
獲取當前目標
不要使用 runlevel 命令了:
$ systemctl list-units --type=target
創建新目標
在 Fedora 中,啟動級別 0、1、3、5、6 都被賦予特定用途。而且都對應一個 systemd 的目標。然而,沒有什么非常好的移植用戶定義的啟動級別(2、4)的方法。要實現相似功能,能夠以原有的啟動級別為基礎。創建一個新的目標 /etc/systemd/system/<新目標>(能夠參考 /usr/lib/systemd/system/graphical.target),創建 /etc/systemd/system/<新目標>.wants 文件夾,向當中加入額外服務的鏈接(指向 /usr/lib/systemd/system/ 中的單元文件)。
目標表
SysV 啟動級別 | Systemd 目標 | 凝視 |
---|---|---|
0 | runlevel0.target, poweroff.target | 中斷系統(halt) |
1, s, single | runlevel1.target, rescue.target | 單用戶模式 |
2, 4 | runlevel2.target, runlevel4.target, multi-user.target | 用戶自己定義啟動級別。通常識別為級別3。 |
3 | runlevel3.target, multi-user.target | 多用戶,無圖形界面。用戶能夠通過終端或網絡登錄。 |
5 | runlevel5.target, graphical.target | 多用戶。圖形界面。繼承級別3的服務。並啟動圖形界面服務。 |
6 | runlevel6.target, reboot.target | 重新啟動 |
emergency | emergency.target | 急救模式(Emergency shell) |
切換啟動級別/目標
systemd 中。啟動級別通過“目標單元”訪問。通過例如以下命令切換:
# systemctl isolate graphical.target
該命令對下次啟動無影響。
等價於telinit 3 或 telinit 5。
改動默認啟動級別/目標
開機啟動進的目標是 default.target。默認鏈接到 graphical.target (大致相當於原來的啟動級別5)。
能夠通過內核參數更改默認啟動級別:
- systemd.unit=multi-user.target (大致相當於級別3)
- systemd.unit=rescue.target (大致相當於級別1)
還有一個方法是改動 default.target。能夠通過 systemctl 改動它:
# systemctl set-default multi-user.target
要覆蓋已經設置的default.target。請使用 force:
# systemctl set-default -f multi-user.target
能夠在 systemctl 的輸出中看到命令執行的效果:鏈接 /etc/systemd/system/default.target 被創建。指向新的默認啟動級別。