名稱
systemd.unit — 單元配置
大綱
, service
.service
, socket
.socket
, device
.device
, mount
.mount
, automount
.automount
, swap
.swap
, target
.target
, path
.path
, timer
.timer
, slice
.slicescope
.scope
系統單元
/etc/systemd/system.control/*
/run/systemd/system.control/*
/run/systemd/transient/*
/run/systemd/generator.early/*
/etc/systemd/system/*
/etc/systemd/systemd.attached/*
/run/systemd/system/*
/run/systemd/systemd.attached/*
/run/systemd/generator/*
…
/usr/lib/systemd/system/*
/run/systemd/generator.late/*
用戶單元(私有用戶單元+全局用戶單元)
~/.config/systemd/user.control/*
$XDG_RUNTIME_DIR/systemd/user.control/*
$XDG_RUNTIME_DIR/systemd/transient/*
$XDG_RUNTIME_DIR/systemd/generator.early/*
~/.config/systemd/user/*
/etc/systemd/user/*
$XDG_RUNTIME_DIR/systemd/user/*
/run/systemd/user/*
$XDG_RUNTIME_DIR/systemd/generator/*
~/.local/share/systemd/user/*
…
/usr/lib/systemd/user/*
$XDG_RUNTIME_DIR/systemd/generator.late/*
描述
單元文件是 ini 風格的純文本文件。 封裝了有關下列對象的信息: 服務(service)、套接字(socket)、設備(device)、掛載點(mount)、自動掛載點(automount)、 啓動目標(target)、交換分區或交換文件(swap)、被監視的路徑(path)、任務計劃(timer)、 資源控制組(slice)、一組外部創建的進程(scope)。參見 systemd.syntax(5) 以瞭解通用配置語法。
本手冊列出了各類單元所共有的配置選項(亦稱"配置指令"或"單元屬性"), 這些選項位於單元文件的 [Unit] 或 [Install] 小節。
除了通用的 [Unit] 與 [Install] 小節之外, 每種單元還有各自 專屬的小節。 詳見各種單元的手冊: systemd.service(5), systemd.socket(5), systemd.device(5), systemd.mount(5), systemd.automount(5), systemd.swap(5), systemd.target(5), systemd.path(5), systemd.timer(5), systemd.slice(5), systemd.scope(5).
單元文件將會從多個編譯時設定的目錄中加載, 下一小節將會詳細解釋。
單元文件可以通過一個"實例名"參數從"模板文件"構造出來(這個過程叫"實例化")。 "模板文件"(也稱"模板單元"或"單元模板")是定義一系列同類型單元的基礎。 模板文件的名稱必須以 "@
" 結尾(在類型後綴之前)。 通過實例化得到的單元,其完整的單元名稱是在模板文件的類型後綴與 "@
" 之間插入實例名稱形成的。在通過實例化得到的單元內部, 可以使用 "%i
" 以及其他說明符來引用實例參數, 詳見後文。
除了手冊中列出的選項之外,單元文件還可以包含更多其他選項。 無法識別的選項不會中斷單元文件的加載,但是 systemd 會輸出一條警告日誌。 如果選項或者小節的名字以 X-
開頭, 那麼 systemd 將會完全忽略它。 以 X-
開頭的小節中的選項沒必要再以 X-
開頭, 因爲整個小節都已經被忽略。 應用程序可以利用這個特性在單元文件中包含額外的信息。
如果想要給一個單元賦予別名,那麼可以按照需求,在系統單元目錄或用戶單元目錄中, 創建一個軟連接(以別名作爲文件名),並將其指向該單元的單元文件。 例如 systemd-networkd.service
在安裝時就通過 /usr/lib/systemd/system/dbus-org.freedesktop.network1.service
軟連接創建了 dbus-org.freedesktop.network1.service
別名。 此外,還可以直接在單元文件的 [Install] 小節中使用 Alias=
創建別名。 注意,單元文件中設置的別名會隨着單元的啓用(enable)與禁用(disable)而生效和失效, 也就是別名軟連接會隨着單元的啓用(enable)與禁用(disable)而創建與刪除。 例如,因爲 reboot.target
單元文件中含有 Alias=ctrl-alt-del.target
的設置,所以啓用(enable)此單元之後,按下 CTRL+ALT+DEL 組合鍵將會導致啓動該單元。單元的別名可以用於 enable, disable, start, stop, status, … 這些命令中,也可以用於 Wants=
, Requires=
, Before=
, After=
, … 這些依賴關係選項中。 但是務必注意,不可將單元的別名用於 preset 命令中。 再次提醒,通過 Alias=
設置的別名僅在單元被啓用(enable)之後纔會生效。
對於例如 foo.service
這樣的單元文件, 可以同時存在對應的 foo.service.wants/
與 foo.service.requires/
目錄, 其中可以放置許多指向其他單元文件的軟連接。 軟連接所指向的單元將會被隱含的添加到 foo.service
相應的 Wants=
與 Requires=
依賴中。 這樣就可以方便的爲單元添加依賴關係,而無需修改單元文件本身。 向 .wants/
與 .requires/
目錄中添加軟連接的首選方法是使用 systemctl(1) 的 enable 命令, 它會讀取單元文件的 [Install] 小節(詳見後文)。
對於例如 foo.service
這樣的單元文件,可以同時存在對應的 foo.service.d/
目錄, 當解析完主單元文件之後,目錄中所有以 ".conf
" 結尾的文件,都會被按照文件名的字典順序,依次解析(相當於依次附加到主單元文件的末尾)。 這樣就可以方便的修改單元的設置,或者爲單元添加額外的設置,而無需修改單元文件本身。 注意,配置片段(".conf
" 文件)必須包含明確的小節頭(例如 "[Service]
" 之類)。 對於從模板文件實例化而來的單元,會優先讀取與此實例對應的 ".d/
" 目錄(例如 "[email protected]/
")中的配置片段(".conf
" 文件), 然後纔會讀取與模板對應的 ".d/
" 目錄(例如 "[email protected]/
")中的配置片段(".conf
" 文件)。 對於名稱中包含連字符("-
")的單元,將會按特定順序依次在一組(而不是一個)目錄中搜索單元配置片段。 例如對於 foo-bar-baz.service
單元來說,將會依次在 foo-.service.d/
, foo-bar-.service.d/
, foo-bar-baz.service.d/
目錄下搜索單元配置片段。這個機制可以方便的爲一組相關單元(單元名稱的前綴都相同)定義共同的單元配置片段, 特別適合應用於 mount, automount, slice 類型的單元, 因爲這些單元的命名規則就是基於連字符構建的。 注意,在前綴層次結構的下層目錄中的單元配置片段,會覆蓋上層目錄中的同名文件, 也就是 foo-bar-.service.d/10-override.conf
會覆蓋(取代) foo-.service.d/10-override.conf
文件。
存放配置片段(".conf
" 文件)的 ".d/
" 目錄, 除了可以放置在 /etc/systemd/{system,user}
目錄中, 還可以放置在 /usr/lib/systemd/{system,user}
與 /run/systemd/{system,user}
目錄中。 雖然在優先級上,/etc
中的配置片段優先級最高、/run
中的配置片段優先級居中、 /usr/lib
中的配置片段優先級最低。但是這僅對同名配置片段之間的覆蓋關係有意義。 因爲所有 ".d/
" 目錄中的配置片段,無論其位於哪個目錄, 都會被按照文件名的字典順序,依次覆蓋單元文件中的設置(相當於依次附加到主單元文件的末尾)。
注意,雖然 systemd 爲明確設置單元之間的依賴關係提供了靈活的方法, 但是我們反對使用這些方法,你應該僅在萬不得已的時候才使用它。 我們鼓勵你使用基於 D-Bus 或 socket 的啓動機制, 以將單元之間的依賴關係隱含化, 從而得到一個更簡單也更健壯的系統。
如上所述,單元可以從模板實例化而來。 這樣就可以用同一個模板文件衍生出多個單元。 當 systemd 查找單元文件時,會首先查找與單元名稱完全吻合的單元文件, 如果沒有找到,並且單元名稱中包含 "@
" 字符, 那麼 systemd 將會繼續查找擁有相同前綴的模板文件, 如果找到,那麼將從這個模板文件實例化一個單元來使用。 例如,對於 [email protected]
單元來說, 其對應的模板文件是 [email protected]
(也就是去掉 "@
" 與後綴名之間的部分)。
可以在模板文件內部 通過 "%i
" 引用實例字符串(也就是上例中的"tty3"), 詳見後面的小節。
如果一個單元文件的大小爲零字節或者是指向 /dev/null
的軟連接, 那麼它的所有相關配置都將被忽略。同時,該單元將被標記爲 "masked
" 狀態,並且無法被啓動。 這樣就可以 徹底屏蔽一個單元(即使手動啓動也不行)。
單元文件的格式在未來將保持穩定(參見 Interface Stability Promise)。
單元名稱中的字符轉義
有時需要將任意字符串(可以包含任意非NUL字符)轉化爲合法有效的單元名稱。 爲了達成這個目標,必須對特殊字符進行轉義。 一個典型的例子是,爲了便於識別,需要將某些單元的名稱精確對應到文件系統上的對象。 例如將 dev-sda.device
與 /dev/sda
精確對應。
轉義規則如下:(1)將 "/
" 替換爲 "-
" ; (2)保持 ASCII字母與數字 不變; (3)保持 "_
" 不變; (4)僅當 ".
" 是首字符時將其替換爲"\x2e",否則保持不變; (5)將上述 1~4 之外的所有其他字符替換爲C風格的"\x??"轉義序列。
對於文件系統路徑來說,"/"的轉義規則略有不同,具體說來就是: (1)單純的根目錄"/"將被替換爲"-"; (2)將其他路徑首尾的"/"刪除後再將剩餘的"/"替換爲"-"。 例如 /foo//bar/baz/
將被轉義爲 "foo-bar-baz
"
只要知道轉義對象是否爲文件系統路徑, 這種轉義規則就是完全可逆的。 systemd-escape(1) 可以用來轉義與還原字符串。使用 systemd-escape --path 轉義文件系統路徑, 使用 systemd-escape 轉義其他字符串。
自動依賴
隱含依賴
許多依賴關係是根據單元的類型與設置自動隱含創建的。 這些隱含的依賴關係可以讓單元文件的內容更加簡潔清爽。 對於各類單元的隱含依賴關係, 可以參考對應手冊頁的"隱含依賴"小節。
例如,帶有 Type=dbus
的 service 單元 將會自動隱含 Requires=dbus.socket
與 After=dbus.socket
依賴。詳見 systemd.service(5) 手冊。
默認依賴
默認依賴與隱含依賴類似,不同之處在於默認依賴可以使用 DefaultDependencies=
選項進行開關(默認值 yes
表示開啓默認依賴,而設爲 no
則表示關閉默認依賴), 而隱含依賴永遠有效。 對於各類單元的默認依賴關係,可以參考對應手冊頁的"默認依賴"小節。
例如,除非明確設置了 DefaultDependencies=no
,否則 target 單元將會默認添加對通過 Wants=
或 Requires=
匯聚的單元 的 After=
依賴。 詳見 systemd.target(5) 手冊。注意,可以通過設置 DefaultDependencies=no
來關閉默認行爲。
單元目錄(單元文件加載路徑)
systemd 將會從一組在編譯時設定好的"單元目錄"中加載單元文件(詳見下面的兩個表格), 並且較先列出的目錄擁有較高的優先級(細節見後文)。 也就是說,高優先級目錄中的文件, 將會覆蓋低優先級目錄中的同名文件。
如果設置了 $SYSTEMD_UNIT_PATH
環境變量, 那麼它將會取代預設的單元目錄。 如果 $SYSTEMD_UNIT_PATH
以 ":
" 結尾, 那麼預設的單元目錄將會被添加到該變量值的末尾。
表 1. 當 systemd 以系統實例(--system
)運行時,加載單元的先後順序(較前的目錄優先級較高):
系統單元目錄 | 描述 |
---|---|
/etc/systemd/system.control |
通過 dbus API 創建的永久系統單元 |
/run/systemd/system.control |
通過 dbus API 創建的臨時系統單元 |
/run/systemd/transient |
動態配置的臨時單元(系統與全局用戶共用) |
/run/systemd/generator.early |
生成的高優先級單元(系統與全局用戶共用)(參見 systemd.generator(7) 手冊中對 early-dir 的說明) |
/etc/systemd/system |
本地配置的系統單元 |
/run/systemd/system |
運行時配置的系統單元 |
/run/systemd/generator |
生成的中優先級系統單元(參見 systemd.generator(7) 手冊中對 normal-dir 的說明) |
/usr/local/lib/systemd/system |
本地軟件包安裝的系統單元 |
/usr/lib/systemd/system |
發行版軟件包安裝的系統單元 |
/run/systemd/generator.late |
生成的低優先級系統單元(參見 systemd.generator(7) 手冊中對 late-dir 的說明) |
表 2. 當 systemd 以用戶實例(--user
)運行時,加載單元的先後順序(較前的目錄優先級較高):
用戶單元目錄 | 描述 |
---|---|
$XDG_CONFIG_HOME/systemd/user.control 或 ~/.config/systemd/user.control |
通過 dbus API 創建的永久私有用戶單元(僅在未設置 $XDG_CONFIG_HOME 時才使用 ~/.config 來替代) |
$XDG_RUNTIME_DIR/systemd/user.control |
通過 dbus API 創建的臨時私有用戶單元 |
/run/systemd/transient |
動態配置的臨時單元(系統與全局用戶共用) |
/run/systemd/generator.early |
生成的高優先級單元(系統與全局用戶共用)(參見 systemd.generator(7) 手冊中對 early-dir 的說明) |
$XDG_CONFIG_HOME/systemd/user 或 $HOME/.config/systemd/user |
用戶配置的私有用戶單元(僅在未設置 $XDG_CONFIG_HOME 時才使用 ~/.config 來替代) |
/etc/systemd/user |
本地配置的全局用戶單元 |
$XDG_RUNTIME_DIR/systemd/user |
運行時配置的私有用戶單元(僅當 $XDG_RUNTIME_DIR 已被設置時有效) |
/run/systemd/user |
運行時配置的全局用戶單元 |
$XDG_RUNTIME_DIR/systemd/generator |
生成的中優先級私有用戶單元(參見 systemd.generator(7) 手冊中對 normal-dir 的說明) |
$XDG_DATA_HOME/systemd/user 或 $HOME/.local/share/systemd/user |
軟件包安裝在用戶家目錄中的私有用戶單元(僅在未設置 $XDG_DATA_HOME 時才使用 ~/.local/share 來替代) |
$dir/systemd/user (對應 $XDG_DATA_DIRS 中的每一個目錄($dir )) |
額外安裝的全局用戶單元,對應 $XDG_DATA_DIRS (默認值="/usr/local/share/:/usr/share/") 中的每一個目錄。 |
/usr/local/lib/systemd/user |
本地軟件包安裝的全局用戶單元 |
/usr/lib/systemd/user |
發行版軟件包安裝的全局用戶單元 |
$XDG_RUNTIME_DIR/systemd/generator.late |
生成的低優先級私有用戶單元(參見 systemd.generator(7) 手冊中對 late-dir 的說明) |
可以使用環境變量來 擴充或更改 systemd 用戶實例(--user
)的單元文件加載路徑。 環境變量可以通過環境變量生成器(詳見 systemd.environment-generator(7) 手冊)來設置。特別地, $XDG_DATA_HOME
與 $XDG_DATA_DIRS
可以方便的通過 systemd-environment-d-generator(8) 來設置。這樣,上表中列出的單元目錄正好就是默認值。 要查看實際使用的、基於編譯選項與當前環境變量的單元目錄列表,可以使用
systemd-analyze --user unit-paths
此外,還可以通過 systemctl(1) 的 link 命令 向上述單元目錄中添加額外的單元(不在上述常規單元目錄中的單元)。
單元垃圾回收
systemd 會在首次引用一個單元時自動加載該單元的配置, 並在不再需要該單元時自動卸載該單元的配置與狀態(垃圾回收)。 可以通過多種不同機制引用單元:
-
該單元是另外一個已加載單元的依賴,例如
After=
,Wants=
, … -
該單元正在啓動(starting)、運行(running)、重新加載配置(reloading)、停止(stopping)
-
該單元正處於失敗(
failed
)狀態(詳見下文) -
該單元的一個任務正在排隊等候執行
-
該單元正在被一個活動的IPC客戶端程序鎖定
-
該單元是一個特殊的"永久"單元,總是被加載並啓動。 例如,根文件系統掛載點
-.mount
單元、以及 systemd(PID=1) 自身所在的init.scope
單元。 -
該單元擁有與其關聯的、正在運行中的進程
可以使用 CollectMode=
選項設置垃圾回收策略, 也就是,是否允許自動卸載處於失敗(failed
)狀態的單元 (詳見下文)。
當一個單元的配置與狀態被卸載之後,該單元的所有執行結果,除了已經記錄在日誌中的信息之外,所有其他信息, 例如,退出碼、退出信號、資源佔用,等等,都會消失。
即使單元的配置已經加載,也可以使用 systemctl daemon-reload 或其他等效命令,強制重新加載單元配置。 所有已經加載的配置都將被清空, 並被新加載的配置取代(當然,新配置未必就立即生效), 同時所有運行時狀態都會被保存並恢復。
[Unit] 小節選項
單元文件中的 [Unit] 小節 包含與單元類型無關的通用信息。 可用的選項(亦稱"指令"或"屬性")如下:
Description=
有利於人類閱讀的、對單元進行簡單描述的字符串。將被 systemd 或其他程序用來標記此單元, 這個字符串應該只用於識別此單元即可,不需要過分說明。例如 "Apache2 Web Server
" 就是一個好例子,而 "high-performance light-weight HTTP server
" (太通用) 與 "Apache2
" (信息太少) 則是兩個壞例子。因爲 systemd 將會把這個字符串用於狀態信息中("Starting
", "description
...Started
", "description
.Reached target
", "description
.Failed to start
"),所以這個字符串應該表現的像一個名詞, 而不是一個完整的句子或帶有動詞的短語。比如 "description
.exiting the container
" 或 "updating the database once per day.
" 就是典型的壞例子。
Documentation=
一組用空格分隔的文檔URI列表, 這些文檔是對此單元的詳細說明。 可接受 "http://
", "https://
", "file:
", "info:
", "man:
" 五種URI類型。 有關URI語法的詳細說明,參見 uri(7) 手冊。 這些URI應該按照相關性由高到低列出。 比如,將解釋該單元作用的文檔放在第一個, 最好再緊跟單元的配置說明, 最後再附上其他文檔。 可以多次使用此選項, 依次向文檔列表尾部添加新文檔。 但是,如果爲此選項設置一個空字符串, 那麼表示 清空先前已存在的列表。
Requires=
設置此單元所必須依賴的其他單元。當啓動此單元時,也必須啓動這裏列出的所有其他單元。 如果此處列出的某個單元啓動失敗、並且恰好又設置了到這個失敗單元的 After=
依賴,那麼將不會啓動此單元。此外,無論是否設置了到被依賴單元的 After=
依賴,只要某個被依賴的單元被顯式停止,那麼該單元也會被連帶停止。 想要添加多個單元,可以多次使用此選項,也可以設置一個空格分隔的單元列表。 注意,此選項並不影響單元之間的啓動或停止順序。 要想調整單元之間的啓動或停止順序,請使用 After=
或 Before=
選項。 例如,在 foo.service
中設置了 Requires=bar.service
, 但是並未使用 After=
或 Before=
設定兩者的啓動順序, 那麼,當需要啓動 foo.service
的時候,這兩個單元會被並行的同時啓動。 建議使用 Wants=
代替 Requires=
來設置單元之間的非致命依賴關係, 從而有助於獲得更好的健壯性, 特別是在某些單元啓動失敗的時候。
注意,設置了此依賴並不意味着當本單元處於運行狀態時,被依賴的其他單元也必須總是處於運行狀態。 例如:(1)失敗的條件檢查(例如後文的 ConditionPathExists=
, ConditionPathIsSymbolicLink=
, …)只會導致被依賴的單元跳過啓動,而不會導致被依賴的單元啓動失敗(也就是進入"failed"狀態)。 (2)某些被依賴的單元可能會自己主動停止(例如有的服務進程可能會主動乾淨的退出、有的設備可能被用戶拔出), 而不會導致本單元自身也跟着一起停止。 要想達到這樣的效果,可以同時聯合使用 BindsTo=
與 After=
依賴,這樣就可以確保:在被依賴的其他單元沒有處於運行狀態時, 本單元自身永遠不會啓動成功(詳見後文)。
注意, 此種依賴關係也可以在單元文件之外通過向 .requires/
目錄中添加軟連接來設置。 詳見前文。
Requisite=
與 Requires=
類似。不同之處在於:當此單元啓動時,這裏列出的依賴單元必須已經全部處於啓動成功的狀態, 否則,此單元將會立即進入啓動失敗的狀態,並且也不會啓動那些尚未成功啓動的被依賴單元。 因爲 Requisite=
不隱含任何順序依賴(即使兩個單元在同一個事務中啓動), 所以,此選項經常與 After=
一起使用, 以確保此單元不會在啓動時間上早於被依賴的單元。
如果 a.service
中包含了 Requisite=b.service
,那麼這個依賴關係將在 b.service
的屬性列表中顯示爲 RequisiteOf=a.service
。 也就是說,不能直接設置 RequisiteOf=
依賴。
Wants=
此選項是 Requires=
的弱化版。 當此單元被啓動時, 所有這裏列出的其他單元只是儘可能被啓動。 但是,即使某些單元不存在或者未能啓動成功, 也不會影響此單元的啓動。 推薦使用此選項來設置單元之間的依賴關係。
注意, 此種依賴關係也可以在單元文件之外通過向 .wants/
目錄中添加軟連接來設置, 詳見前文。
BindsTo=
與 Requires=
類似,但是依賴性更強: 如果這裏列出的任意一個單元停止運行或者崩潰,那麼也會連帶導致該單元自身被停止。 這就意味着該單元可能因爲 這裏列出的任意一個單元的 主動退出、某個設備被拔出、某個掛載點被卸載, 而被強行停止。
如果將某個被依賴的單元同時放到 After=
與 BindsTo=
選項中,那麼效果將會更加強烈:被依賴的單元必須嚴格的先於本單元啓動成功之後, 本單元才能開始啓動。這就意味着,不但在被依賴的單元意外停止時,該單元必須停止, 而且在被依賴的單元由於條件檢查失敗(例如後文的 ConditionPathExists=
, ConditionPathIsSymbolicLink=
, …)而被跳過時, 該單元也將無法啓動。正因爲如此,在很多場景下,需要同時使用 BindsTo=
與 After=
選項。
如果 a.service
中包含了 BindsTo=b.service
,那麼這個依賴關係將在 b.service
的屬性列表中顯示爲 BoundBy=a.service
。 也就是說,不能直接設置 BoundBy=
依賴。
PartOf=
與 Requires=
類似, 不同之處在於:僅作用於單元的停止或重啓。 其含義是,當停止或重啓這裏列出的某個單元時, 也會同時停止或重啓該單元自身。 注意,這個依賴是單向的, 該單元自身的停止或重啓並不影響這裏列出的單元。
如果 a.service
中包含了 PartOf=b.service
,那麼這個依賴關係將在 b.service
的屬性列表中顯示爲 ConsistsOf=a.service
。 也就是說,不能直接設置 ConsistsOf=
依賴。
Conflicts=
指定單元之間的衝突關係。 接受一個空格分隔的單元列表,表明該單元不能與列表中的任何單元共存, 也就是說:(1)當此單元啓動的時候,列表中的所有單元都將被停止; (2)當列表中的某個單元啓動的時候,該單元同樣也將被停止。 注意,此選項與 After=
和 Before=
選項沒有任何關係。
如果兩個相互衝突的單元A與B 需要在同一個事務內作爲B啓動, 那麼這個事務要麼會失敗(A與B都是事務中的必要部分[Requires]), 要麼就是必須被修改(A與B中至少有一個是事務中的非必要部分)。 在後一種情況下, 將會剔除一個非必要的單元 (若兩個都是非必要的單元, 則優先剔除A)。
Before=
, After=
強制指定單元之間的先後順序,接受一個空格分隔的單元列表。 假定 foo.service
單元包含 Before=bar.service
設置, 那麼當兩個單元都需要啓動的時候, bar.service
將會一直延遲到 foo.service
啓動完畢之後再啓動。 注意,停止順序與啓動順序正好相反,也就是說, 只有當 bar.service
完全停止後,纔會停止 foo.service
單元。 After=
的含義與 Before=
正好相反。 假定 foo.service
單元包含 After=bar.service
設置, 那麼當兩個單元都需要啓動的時候, foo.service
將會一直延遲到 bar.service
啓動完畢之後再啓動。 注意,停止順序與啓動順序正好相反,也就是說, 只有當 foo.service
完全停止後,纔會停止 bar.service
單元。 注意,此二選項僅用於指定先後順序, 而與 Requires=
, Wants=
, BindsTo=
這些選項沒有任何關係。 不過在實踐中也經常遇見將某個單元同時設置到 After=
與 Requires=
選項中的情形。 可以多次使用此二選項,以將多個單元添加到列表中。 假定兩個單元之間存在先後順序(無論誰先誰後),並且一個要停止而另一個要啓動,那麼永遠是"先停止後啓動"的順序。 但如果兩個單元之間沒有先後順序,那麼它們的停止和啓動就都是相互獨立的,並且是並行的。 對於不同類型的單元來說,判斷啓動是否已經完成的標準並不完全相同。 特別的,對於設置在 Before=
/After=
中的服務單元來說, 只有在服務單元內配置的所有啓動命令全部都已經被調用,並且對於每一個被調用的命令, 要麼確認已經調用失敗、要麼確認已經成功運行的情況下, 才能認爲已經完成啓動。
OnFailure=
接受一個空格分隔的單元列表。 當該單元進入失敗("failed
")狀態時, 將會啓動列表中的單元。使用了 Restart=
的服務單元僅在超出啓動頻率限制之後, 纔會進入失敗(failed)狀態。
PropagatesReloadTo=
, ReloadPropagatedFrom=
接受一個空格分隔的單元列表。 PropagatesReloadTo=
表示 在 reload 該單元時, 也同時 reload 所有列表中的單元。 ReloadPropagatedFrom=
表示 在 reload 列表中的某個單元時, 也同時 reload 該單元。
JoinsNamespaceOf=
接受一個空格分隔的單元列表, 表示將該單元所啓動的進程加入到列表單元的網絡及 臨時文件(/tmp
, /var/tmp
)的名字空間中。 此選項僅適用於支持 PrivateNetwork=
與/或 PrivateTmp=
指令的單元(對加入者與被加入者都適用)。詳見 systemd.exec(5) 手冊。 如果單元列表中 僅有一個單元處於已啓動狀態, 那麼該單元將加入到 這個唯一已啓動單元的名字空間中。 如果單元列表中 有多個單元處於已啓動狀態, 那麼該單元將 隨機加入一個已啓動單元的 名字空間中。
RequiresMountsFor=
接受一個空格分隔的絕對路徑列表,表示該單元將會使用到這些文件系統路徑。 所有這些路徑中涉及的掛載點所對應的 mount 單元,都會被隱式的添加到 Requires=
與 After=
選項中。 也就是說,這些路徑中所涉及的掛載點都會在啓動該單元之前被自動掛載。
注意,雖然帶有 noauto
標記的掛載點不會被 local-fs.target
自動掛載, 但是它並不影響此選項所設置的依賴關係。 也就是說,帶有 noauto
標記的掛載點 依然會在啓動該單元之前被自動掛載。
OnFailureJobMode=
可設爲 "fail
", "replace
", "replace-irreversibly
", "isolate
", "flush
", "ignore-dependencies
", "ignore-requirements
" 之一。 默認值是 "replace
" 。 指定 OnFailure=
中列出的單元應該以何種方式排隊。值的含義參見 systemctl(1) 手冊中對 --job-mode=
選項的說明。 如果設爲 "isolate
" , 那麼只能在 OnFailure=
中設置一個單獨的單元。
IgnoreOnIsolate=
接受一個布爾值。設爲 yes
表示在執行 systemctl isolate ... 命令時,此單元不會被停止。 對於 service, target, socket, timer, path 單元來說,默認值是 false
; 對於 slice, scope, device, swap, mount, automount 單元來說, 默認值是 true
。
StopWhenUnneeded=
如果設爲 yes
, 那麼當此單元不再被任何已啓動的單元依賴時, 將會被自動停止。 默認值 no
的含義是, 除非此單元與其他即將啓動的單元衝突, 否則即使此單元已不再被任何已啓動的單元依賴, 也不會自動停止它。
RefuseManualStart=
, RefuseManualStop=
如果設爲 yes
, 那麼此單元將拒絕被手動啓動(RefuseManualStart=
) 或拒絕被手動停止(RefuseManualStop=
)。 也就是說, 此單元只能作爲其他單元的依賴條件而存在, 只能因爲依賴關係而被間接啓動或者間接停止, 不能由用戶以手動方式直接啓動或者直接停止。 設置此選項是爲了 禁止用戶意外的啓動或者停止某些特定的單元。 默認值是 no
AllowIsolate=
如果設爲 yes
, 那麼此單元將允許被 systemctl isolate 命令操作, 否則將會被拒絕。 唯一一個將此選項設爲 yes
的理由,大概是爲了兼容SysV初始化系統。 此時應該僅考慮對 target 單元進行設置, 以防止系統進入不可用狀態。 建議保持默認值 no
DefaultDependencies=
默認值 yes
表示爲此單元隱式地創建默認依賴。 不同類型的單元,其默認依賴也不同,詳見各自的手冊頁。 例如對於 service 單元來說, 默認的依賴關係是指: (1)開機時,必須在基礎系統初始化完成之後才能啓動該服務; (2)關機時,必須在該服務完全停止後才能關閉基礎系統。 通常,只有那些在系統啓動的早期就必須啓動的單元, 以及那些必須在系統關閉的末尾才能關閉的單元, 纔可以將此選項設爲 no
。 注意,設爲 no
並不表示取消所有的默認依賴, 只是表示取消非關鍵的默認依賴。 強烈建議對絕大多數普通單元 保持此選項的默認值 yes
。
CollectMode=
設置此單元的"垃圾回收"策略。可設爲 inactive
(默認值) 或 inactive-or-failed
之一。默認值 inactive
表示如果該單元處於停止(inactive
)狀態,並且沒有被其他客戶端、任務、單元所引用,那麼該單元將會被卸載。 注意,如果此單元處於失敗(failed
)狀態,那麼是不會被卸載的, 它會一直保持未卸載狀態,直到用戶調用 systemctl reset-failed (或類似的命令)重置了 failed
狀態。設爲 inactive-or-failed
表示無論此單元處於停止(inactive
)狀態還是失敗(failed
)狀態, 都將被卸載(無需重置 failed
狀態)。 注意,在這種"垃圾回收"策略下, 此單元的所有結果(退出碼、退出信號、資源消耗 …) 都會在此單元結束之後立即清除(只剩下此前已經記錄在日誌中的痕跡)。
FailureAction=
, SuccessAction=
當此單元停止並進入失敗(failed
)或停止(inactive
)狀態時,應當執行什麼動作。 對於系統單元,可以設爲 none
, reboot
, reboot-force
, reboot-immediate
, poweroff
, poweroff-force
, poweroff-immediate
, exit
, exit-force
之一。 對於用戶單元,僅可設爲 none
, exit
, exit-force
之一。兩個選項的默認值都是 none
默認值 none
表示 不觸發任何動作。 reboot
/poweroff
表示按照常規關機流程重啓/關閉整個系統(等價於 systemctl reboot|poweroff)。 reboot-force
/poweroff-force
表示強制殺死所有進程之後強制重啓/關機, 雖然可能會造成應用程序數據丟失,但是不會造成文件系統不一致(等價於 systemctl reboot|poweroff -f)。 reboot-immediate
/poweroff-immediate
表示強制立即執行 reboot(2) 系統調用重啓/關機, 可能會造成數據丟失以及文件系統不一致(等價於 systemctl reboot|poweroff -ff)。 exit
表示按照常規關閉流程,按部就班的退出 systemd 系統管理器。 exit-force
表示立即強制退出 systemd 系統管理器(不再按部就班的逐一退出全部服務)。 當設爲 exit
或 exit-force
時, systemd 系統管理器將會默認把此單元主進程的返回值(如果有)用作系統管理器自身的返回值。 當然,這個默認行爲可以通過下面的 FailureActionExitStatus=
/SuccessActionExitStatus=
進行修改。
FailureActionExitStatus=
, SuccessActionExitStatus=
當 FailureAction=
/SuccessAction=
的值爲 exit
或 exit-force
之一,並且設定的動作被觸發時,應該返回什麼樣退出碼給容器管理器(對於系統服務) 或 systemd 系統管理器(對於用戶服務)。 默認情況下,將會使用該單元主進程的退出碼(如果有)。 取值範圍是 0…255 之間的一個整數。 設爲空字符串表示重置回默認行爲。
JobTimeoutSec=
, JobRunningTimeoutSec=
當該單元的一個任務(job)進入隊列的時候, JobTimeoutSec=
用於設置從該任務進入隊列開始計時、到該任務最終完成,最多可以使用多長時間, JobRunningTimeoutSec=
用於設置從該任務實際運行開始計時、到該任務最終完成,最多可以使用多長時間。 如果上述任意一個設置超時,那麼超時的任務將被撤銷,並且該單元將保持其現有狀態不變(而不是進入 "failed
" 狀態)。 對於非 device 單元來說,DefaultTimeoutStartSec=
選項的默認值是 "infinity
"(永不超時), 而 JobRunningTimeoutSec=
的默認值等於 DefaultTimeoutStartSec=
的值。 注意,此處設置的超時不是指單元自身的超時(例如 TimeoutStartSec=
就是指單元自身的超時), 而是指該單元在啓動或者停止等狀態變化過程中,等候某個外部任務完成的最長時限。 換句話說,適用於單元自身的超時設置(例如 TimeoutStartSec=
)用於指定單元自身在改變其狀態時,總共允許使用多長時間; 而此處設置的超時則是設置此單元在改變其狀態的過程中,等候某個外部任務完成所能容忍的最長時間。
JobTimeoutAction=
, JobTimeoutRebootArgument=
JobTimeoutAction=
用於指定當超時發生時(參見上文的 JobTimeoutSec=
與 JobRunningTimeoutSec=
選項),將觸發什麼樣的額外動作。 可接受的值與 StartLimitAction=
相同,默認值爲 none
。 JobTimeoutRebootArgument=
用於指定傳遞給 reboot(2) 系統調用的字符串參數。
StartLimitIntervalSec=
, interval
StartLimitBurst=
burst
設置單元的啓動頻率限制。 也就是該單元在 interval
時間內最多允許啓動 burst
次。 StartLimitIntervalSec=
用於設置時長(默認值等於 systemd 配置文件(system.conf)中 DefaultStartLimitIntervalSec=
的值),設爲 0 表示沒有限制。 StartLimitBurst=
用於設置在給定的時長內,最多允許啓動多少次(默認值等於 systemd 配置文件(system.conf)中 DefaultStartLimitBurst=
的值)。 雖然此選項通常與 Restart=
選項(參見 systemd.service(5)) 一起使用, 但實際上,此選項作用於任何方式的啓動(包括手動啓動),而不僅僅是由 Restart=
觸發的啓動。 注意,一旦某個設置了 Restart=
自動重啓邏輯的單元觸碰到了啓動頻率限制, 那麼該單元將再也不會嘗試自動重啓; 不過,如果該單元在經過 interval
時長之後,又被手動重啓成功的話,那麼該單元的自動重啓邏輯將會被再次激活。 注意,systemctl reset-failed 命令能夠重置單元的啓動頻率計數器。 系統管理員在手動啓動某個已經觸碰到了啓動頻率限制的單元之前,可以使用這個命令清除啓動限制。 注意,因爲啓動頻率限制位於所有單元條件檢查之後, 所以基於失敗條件的啓動不會計入啓動頻率限制的啓動次數之中。 注意,這些選項對 slice, target, device, scope 單元沒有意義, 因爲這幾種單元要麼永遠不會啓動失敗、要麼只能成功啓動一次。
當一個單元因爲垃圾回收(見前文)而被卸載的時候, 該單元的啓動頻率計數器也會被一起清除。 這就意味着對不被持續引用的單元設置啓動頻率限制是無效的。
StartLimitAction=
設置該單元在觸碰了 StartLimitIntervalSec=
與 StartLimitBurst=
定義的啓動頻率限制時,將會執行什麼動作。 可接受的值與 FailureAction=
/SuccessAction=
相同,值的含義也相同。 默認值 none
表示除了禁止啓動之外, 不觸發任何其他動作。
RebootArgument=
當 StartLimitAction=
或 FailureAction=
觸發重啓動作時, 此選項的值就是傳遞給 reboot(2) 系統調用的字符串參數。 相當於 systemctl reboot 命令接收的可選參數。
ConditionArchitecture=
, ConditionVirtualization=
, ConditionHost=
, ConditionKernelCommandLine=
, ConditionKernelVersion=
, ConditionSecurity=
, ConditionCapability=
, ConditionACPower=
, ConditionNeedsUpdate=
, ConditionFirstBoot=
, ConditionPathExists=
, ConditionPathExistsGlob=
, ConditionPathIsDirectory=
, ConditionPathIsSymbolicLink=
, ConditionPathIsMountPoint=
, ConditionPathIsReadWrite=
, ConditionDirectoryNotEmpty=
, ConditionFileNotEmpty=
, ConditionFileIsExecutable=
, ConditionUser=
, ConditionGroup=
, ConditionControlGroupController=
這組選項用於在啓動單元之前,首先測試特定的條件是否爲真。 若爲假,則悄無聲息地跳過此單元的啓動(僅是跳過,而不是進入"failed
"狀態)。 注意,即使某單元由於測試條件爲假而被跳過, 那些由於依賴關係而必須先於此單元啓動的單元並不會受到影響(也就是會照常啓動)。 可以使用條件表達式來跳過那些對於本機系統無用的單元, 比如那些對於本機內核或運行環境沒有用處的功能。 如果想要單元在測試條件爲假時, 除了跳過啓動之外,還要在日誌中留下痕跡(而不是悄無聲息的跳過), 可以使用對應的另一組 AssertArchitecture=
, AssertVirtualization=
, … 選項(見後文)。
ConditionArchitecture=
檢測是否運行於 特定的硬件平臺: x86
, x86-64
, ppc
, ppc-le
, ppc64
, ppc64-le
, ia64
, parisc
, parisc64
, s390
, s390x
, sparc
, sparc64
, mips
, mips-le
, mips64
, mips64-le
, alpha
, arm
, arm-be
, arm64
, arm64-be
, sh
, sh64
, m68k
, tilegx
, cris
, arc
, arc-be
, native
(編譯 systemd 時的目標平臺)。 可以在這些關鍵字前面加上感嘆號(!)前綴 表示邏輯反轉。注意, Personality=
的值 對此選項 沒有任何影響。
ConditionVirtualization=
檢測是否運行於(特定的)虛擬環境中: yes
(某種虛擬環境), no
(物理機), vm
(某種虛擬機), container
(某種容器), qemu
, kvm
, zvm
, vmware
, microsoft
, oracle
, xen
, bochs
, uml
, bhyve
, qnx
, openvz
, lxc
, lxc-libvirt
, systemd-nspawn
, docker
, rkt
, private-users
(用戶名字空間)。參見 systemd-detect-virt(1) 手冊以瞭解所有已知的虛擬化技術及其標識符。 如果嵌套在多個虛擬化環境內, 那麼以最內層的那個爲準。 可以在這些關鍵字前面加上感嘆號(!)前綴表示邏輯反轉。
ConditionHost=
檢測系統的 hostname 或者 "machine ID" 。 參數可以是:(1)一個主機名字符串(可以使用 shell 風格的通配符), 該字符串將會與 本機的主機名(也就是 gethostname(2) 的返回值)進行匹配;(2)或者是一個 "machine ID" 格式的字符串(參見 machine-id(5) 手冊)。 可以在字符串前面加上感嘆號(!)前綴表示邏輯反轉。
ConditionKernelCommandLine=
檢測是否設置了某個特定的內核引導選項。 參數可以是一個單獨的單詞,也可以是一個 "var=val
" 格式的賦值字符串。 如果參數是一個單獨的單詞,那麼以下兩種情況都算是檢測成功: (1)恰好存在一個完全匹配的單詞選項; (2)在某個 "var=val
" 格式的內核引導選項中等號前的 "var
" 恰好與該單詞完全匹配。 如果參數是一個 "var=val
" 格式的賦值字符串, 那麼必須恰好存在一個完全匹配的 "var=val
" 格式的內核引導選項,纔算檢測成功。 可以在字符串前面加上感嘆號(!)前綴表示邏輯反轉。
ConditionKernelVersion=
檢測內核版本(uname -r) 是否匹配給定的表達式(或在字符串前面加上感嘆號(!)前綴表示"不匹配")。 表達式必須是一個單獨的字符串。如果表達式以 "<
", "<=
", "=
", ">=
", ">
" 之一開頭, 那麼表示對內核版本號進行比較,否則表示按照 shell 風格的通配符表達式進行匹配。
注意,企圖根據內核版本來判斷內核支持哪些特性是不可靠的。 因爲發行版廠商經常將高版本內核的新驅動和新功能移植到當前發行版使用的低版本內核中, 所以,對內核版本的檢查是不能在不同發行版之間隨意移植的, 不應該用於需要跨發行版部署的單元。
ConditionSecurity=
檢測是否啓用了 特定的安全技術: selinux
, apparmor
, tomoyo
, ima
, smack
, audit
, uefi-secureboot
。 可以在這些關鍵字前面加上感嘆號(!)前綴表示邏輯反轉。
ConditionCapability=
檢測 systemd 的 capability 集合中 是否存在 特定的 capabilities(7) 。 參數應設爲例如 "CAP_MKNOD
" 這樣的 capability 名稱。 注意,此選項不是檢測特定的 capability 是否實際可用,而是僅檢測特定的 capability 在綁定集合中是否存在。 可以在名稱前面加上感嘆號(!)前綴表示邏輯反轉。
ConditionACPower=
檢測系統是否 正在使用交流電源。 yes
表示至少在使用一個交流電源, 或者更本不存在任何交流電源。 no
表示存在交流電源, 但是 沒有使用其中的任何一個。
ConditionNeedsUpdate=
可設爲 /var
或 /etc
之一, 用於檢測指定的目錄是否需要更新。 設爲 /var
表示 檢測 /usr
目錄的最後更新時間(mtime) 是否比 /var/.updated
文件的最後更新時間(mtime)更晚。 設爲 /etc
表示 檢測 /usr
目錄的最後更新時間(mtime) 是否比 /etc/.updated
文件的最後更新時間(mtime)更晚。 可以在值前面加上感嘆號(!)前綴表示邏輯反轉。 當更新了 /usr
中的資源之後,可以通過使用此選項, 實現在下一次啓動時更新 /etc
或 /var
目錄的目的。 使用此選項的單元必須設置 ConditionFirstBoot=systemd-update-done.service
, 以確保在 .updated
文件被更新之前啓動完畢。 參見 systemd-update-done.service(8) 手冊。
ConditionFirstBoot=
可設爲 yes
或 no
。 用於檢測 /etc
目錄是否處於未初始化的原始狀態(重點是 /etc/machine-id
文件是否存在)。 此選項可用於系統出廠後(或者恢復出廠設置之後), 首次開機時執行必要的初始化操作。
ConditionPathExists=
檢測 指定的路徑 是否存在, 必須使用絕對路徑。 可以在路徑前面 加上感嘆號(!)前綴 表示邏輯反轉。
ConditionPathExistsGlob=
與 ConditionPathExists=
類似, 唯一的不同是支持 shell 通配符。
ConditionPathIsDirectory=
檢測指定的路徑是否存在並且是一個目錄,必須使用絕對路徑。 可以在路徑前面加上感嘆號(!)前綴表示邏輯反轉。
ConditionPathIsSymbolicLink=
檢測指定的路徑是否存在並且是一個軟連接,必須使用絕對路徑。 可以在路徑前面加上感嘆號(!)前綴 表示邏輯反轉。
ConditionPathIsMountPoint=
檢測指定的路徑是否存在並且是一個掛載點,必須使用絕對路徑。 可以在路徑前面加上感嘆號(!)前綴表示邏輯反轉。
ConditionPathIsReadWrite=
檢測指定的路徑是否存在並且可讀寫(rw),必須使用絕對路徑。 可以在路徑前面加上感嘆號(!)前綴 表示邏輯反轉。
ConditionDirectoryNotEmpty=
檢測指定的路徑是否存在並且是一個非空的目錄,必須使用絕對路徑。 可以在路徑前面加上感嘆號(!)前綴 表示邏輯反轉。
ConditionFileNotEmpty=
檢測指定的路徑是否存在並且是一個非空的普通文件,必須使用絕對路徑。 可以在路徑前面加上感嘆號(!)前綴 表示邏輯反轉。
ConditionFileIsExecutable=
檢測指定的路徑是否存在並且是一個可執行文件,必須使用絕對路徑。 可以在路徑前面加上感嘆號(!)前綴 表示邏輯反轉。
ConditionUser=
檢測 systemd 是否以給定的用戶身份運行。 參數可以是數字形式的 "UID
" 、 或者字符串形式的UNIX用戶名、 或者特殊值 "@system
"(表示屬於系統用戶範圍內) 。 此選項對於系統服務無效, 因爲管理系統服務的 systemd 進程 總是以 root 用戶身份運行。
ConditionGroup=
檢測 systemd 是否以給定的用戶組身份運行。 參數可以是數字形式的 "GID
" 或者字符串形式的UNIX組名。 注意:(1)這裏所說的"組"可以是"主組"(Primary Group)、"有效組"(Effective Group)、"輔助組"(Auxiliary Group); (2)此選項不存在特殊值 "@system
"
ConditionControlGroupController=
檢測給定的一組 cgroup 控制器(例如 cpu
)是否全部可用。 通過例如 cgroup_disable=controller
這樣的內核命令行可以禁用名爲"controller"的 cgroup 控制器。 列表中的多個 cgroup 控制器之間可以使用空格分隔。 不能識別的 cgroup 控制器將被忽略。 能夠識別的全部 cgroup 控制器如下: cpu
, cpuacct
, io
, blkio
, memory
, devices
, pids
如果在條件之前加上管道符(|),那麼這個條件就是"觸發條件", 其含義是隻要滿足一個觸發條件,該單元就會被啓動; 如果在條件之前沒有管道符(|),那麼這個條件就是"普通條件", 其含義是必須滿足全部普通條件,該單元纔會被啓動。 如果在某個單元文件內, 同時存在"觸發條件"與"普通條件",那麼必須滿足全部普通條件, 並且至少滿足一個觸發條件,該單元纔會被啓動。 如果需要對某個條件同時使用"|"與"!", 那麼"|"必須位於"!"之前。 除 ConditionPathIsSymbolicLink=
之外, 其他路徑檢測選項都會追蹤軟連接。 如果將上述某個檢測選項設爲空字符串, 那麼表示重置該選項先前的所有設置, 也就是清空該選項先前的設置。
AssertArchitecture=
, AssertVirtualization=
, AssertHost=
, AssertKernelCommandLine=
, AssertKernelVersion=
, AssertSecurity=
, AssertCapability=
, AssertACPower=
, AssertNeedsUpdate=
, AssertFirstBoot=
, AssertPathExists=
, AssertPathExistsGlob=
, AssertPathIsDirectory=
, AssertPathIsSymbolicLink=
, AssertPathIsMountPoint=
, AssertPathIsReadWrite=
, AssertDirectoryNotEmpty=
, AssertFileNotEmpty=
, AssertFileIsExecutable=
, AssertUser=
, AssertGroup=
, AssertControlGroupController=
與前一組 ConditionArchitecture=
, ConditionVirtualization=
, … 測試選項類似,這一組選項用於在單元啓動之前, 首先進行相應的斷言檢查。不同之處在於,任意一個斷言的失敗, 都會導致跳過該單元的啓動並將失敗的斷言突出記錄在日誌中。 注意,斷言失敗並不導致該單元進入失敗("failed
")狀態(實際上,該單元的狀態不會發生任何變化), 它僅影響該單元的啓動任務隊列。 如果用戶希望清晰的看到某些單元因爲未能滿足特定的條件而導致沒有正常啓動, 那麼可以使用斷言表達式。
注意,無論是前一組條件表達式、還是這一組斷言表達式,都不會改變單元的狀態。 因爲這兩組表達式都是在啓動任務隊列開始執行時進行檢查(也就是,位於依賴任務隊列之後、該單元自身啓動任務隊列之前), 所以,條件表達式和斷言表達式 都不適合用於對單元的依賴條件進行檢查。
SourcePath=
指定 生成此單元時所參考的配置文件。 僅用於單元生成器 標識此單元生成自何處。 普通的單元 不應該使用它。
單元屬性的正反對應
那些與其他單元關聯的屬性 通常同時顯示(systemctl show)在兩個關聯單元的屬性中。 多數情況下, 屬性的名稱就是單元配置選項的名稱,但並不總是如此。 下表展示了存在依賴關係的兩個單元的屬性是如何顯示的, 同時也展示了"源"單元的屬性與"目標"單元的屬性之間的對應關係。
表 3. "正向"與"反向"單元屬性
"正向"屬性 | "反向"屬性 | 用於何處 |
---|---|---|
Before= |
After= |
[Unit] 小節 |
After= |
Before= |
|
Requires= |
RequiredBy= |
[Unit] 小節; [Install] 小節 |
Wants= |
WantedBy= |
[Unit] 小節; [Install] 小節 |
PartOf= |
ConsistsOf= |
[Unit] 小節; 自動生成 |
BindsTo= |
BoundBy= |
[Unit] 小節; 自動生成 |
Requisite= |
RequisiteOf= |
[Unit] 小節; 自動生成 |
Triggers= |
TriggeredBy= |
自動生成(參見下文的解釋) |
Conflicts= |
ConflictedBy= |
[Unit] 小節; 自動生成 |
PropagatesReloadTo= |
ReloadPropagatedFrom= |
[Unit] 小節 |
ReloadPropagatedFrom= |
PropagatesReloadTo= |
|
Following= |
n/a | 自動生成 |
WantedBy=
與 RequiredBy=
位於 [Install] 小節,僅用於在 .wants/
與 .requires/
目錄中創建軟連接, 不能直接用作單元屬性。
ConsistsOf=
, BoundBy=
, RequisiteOf=
, ConflictedBy=
只能由對應的"正向"屬性自動隱式創建,而不能直接在單元文件中設置。
Triggers=
只能隱式的創建於 socket, path, automount 單元之中。 默認觸發對應的同名單元,但是可以通過 Sockets=
, Service=
, Unit=
選項進行改寫。詳見 systemd.service(5), systemd.socket(5), systemd.path(5), systemd.automount(5) 手冊。TriggeredBy=
只能隱式的創建於被觸發的單元之中。
Following=
用於匯聚設備別名, 並指向用於跟蹤設備狀態的"主"設備單元,通常對應到一個 sysfs 文件系統路徑。 它並不會顯示在"目標"單元中。
[Install] 小節選項
"[Install]
" 小節包含單元的啓用信息。 事實上,systemd(1) 在運行時並不使用此小節。 只有 systemctl(1) 的 enable 與 disable 命令在啓用/停用單元時纔會使用此小節。 [譯者注]"啓用"一個單元多數時候在效果上相當於將這個單元設爲"開機時自動啓動"或"插入某個硬件時自動啓動"; "停用"一個單元多數時候在效果上相當於撤銷該單元的"開機時自動啓動"或"插入某個硬件時自動啓動"。
Alias=
啓用時使用的別名,可以設爲一個空格分隔的別名列表。 每個別名的後綴(也就是單元類型)都必須與該單元自身的後綴相同。 如果多次使用此選項,那麼每個選項所設置的別名都會被添加到別名列表中。 在啓用此單元時,systemctl enable 命令將會爲每個別名創建一個指向該單元文件的軟連接。 注意,因爲 mount, slice, swap, automount 單元不支持別名, 所以不要在這些類型的單元中使用此選項。
WantedBy=
, RequiredBy=
接受一個空格分隔的單元列表, 表示在使用 systemctl enable 啓用此單元時, 將會在每個列表單元的 .wants/
或 .requires/
目錄中創建一個指向該單元文件的軟連接。 這相當於爲每個列表中的單元文件添加了 Wants=此單元
或 Requires=此單元
選項。 這樣當列表中的任意一個單元啓動時,該單元都會被啓動。 有關 Wants=
與 Requires=
的詳細說明, 參見前面 [Unit] 小節的說明。 如果多次使用此選項, 那麼每個選項的單元列表都會合併在一起。
在普通的 bar.service
單元內設置 WantedBy=foo.service 選項 與設置 Alias=foo.service.wants/bar.service 選項基本上是等價的。 但是對於模板單元來說,情況則有所不同。 雖然必須使用實例名稱調用 systemctl enable 命令, 但是實際上添加到 .wants/
或 .requires/
目錄中的軟連接, 指向的卻是模板單元(因爲並不存在真正的單元實例文件)。 假設 [email protected]
文件中存在 WantedBy=getty.target 選項,那麼 systemctl enable [email protected] 命令將會創建一個 getty.target.wants/[email protected]
軟連接(指向 [email protected]
)
Also=
設置此單元的附屬單元, 可以設爲一個空格分隔的單元列表。 表示當使用 systemctl enable 啓用 或 systemctl disable 停用 此單元時, 也同時自動的啓用或停用附屬單元。
如果多次使用此選項, 那麼每個選項所設置的附屬單元列表 都會合併在一起。
DefaultInstance=
僅對模板單元有意義, 用於指定默認的實例名稱。 如果啓用此單元時沒有指定實例名稱, 那麼 將使用這裏設置的名稱。
在 [Install] 小節的選項中,可以使用如下替換符: %n, %N, %p, %i, %j, %g, %G, %U, %u, %m, %H, %b, %v 。 每個符號的具體含義詳見下一小節。
替換符
在許多選項中都可以使用一些替換符(不只是 [Install] 小節中的選項), 以引用一些運行時才能確定的值, 從而可以寫出更通用的單元文件。 替換符必須是已知的、並且是可以解析的,這樣設置才能生效。 當前可識別的所有替換符及其解釋如下:
表 4. 可以用在單元文件中的替換符
替換符 | 含義 |
---|---|
"%b " |
系統的"Boot ID"字符串。參見 random(4) 手冊 |
"%C " |
緩存根目錄。對於系統實例來說是 /var/cache ;對於用戶實例來說是 "$XDG_CACHE_HOME " |
"%E " |
配置根目錄。對於系統實例來說是 /etc ;對於用戶實例來說是 "$XDG_CONFIG_HOME " |
"%f " |
原始單元文件名稱(不含路徑,且遵守前文描述的已轉義絕對文件系統路徑的還原規則)。對於實例化的單元,就是帶有 / 前綴的原始實例名;對於其他單元,就是帶有 / 前綴的原始前綴名。 |
"%h " |
用戶的家目錄。運行 systemd 實例的用戶的家目錄,對於系統實例則是 "/root " |
"%H " |
系統的主機名(hostname) |
"%i " |
已轉義的實例名稱。對於實例化單元,就是 "@ " 和後綴之間的部分。對於非實例化單元則爲空。 |
"%I " |
原始實例名稱。對於實例化單元,就是 "@ " 和後綴之間的部分(已還原的)。對於非實例化單元則爲空。 |
"%j " |
已轉義的前綴名最後一部分。也就是前綴名中最後一個 "- " 之後的部分。如果沒有 "- " 那麼與 "%p " 相同。 |
"%J " |
原始前綴名最後一部分。也就是前綴名中最後一個 "- " 之後的部分(已還原的)。如果沒有 "- " 那麼與 "%p " 相同。 |
"%L " |
日誌根目錄。對於系統實例來說是 /var/log ;對於用戶實例來說是 "$XDG_CONFIG_HOME "/log |
"%m " |
系統的"Machine ID"字符串。參見 machine-id(5) 手冊 |
"%n " |
帶類型後綴的完整單元名稱 |
"%N " |
無類型後綴的完整單元名稱 |
"%p " |
已轉義的前綴名稱。對於實例化單元來說,就是單元名稱裏第一個 "@ " 之前的字符串。對於非實例化單元來說,等價於 "%N " |
"%P " |
原始前綴名稱。對於實例化單元來說,就是單元名稱裏第一個 "@ " 之前的字符串(已還原的)。對於非實例化單元來說,等價於 "%N " |
"%s " |
用戶的shell。運行 systemd 實例的用戶的shell,對於系統實例則是 "/bin/sh " |
"%S " |
狀態根目錄。對於系統實例來說是 /var/lib ;對於用戶實例來說是 "$XDG_CONFIG_HOME " |
"%t " |
運行時根目錄。對於系統實例來說是 /run ;對於用戶實例來說是 "$XDG_RUNTIME_DIR " |
"%T " |
臨時文件目錄。也就是 /tmp 或 "$TMPDIR ", "$TEMP ", "$TMP " 之一(若已設置) |
"%g " |
運行 systemd 用戶實例的組名稱。對於 systemd 系統實例來說,則是 "root " |
"%G " |
運行 systemd 用戶實例的組GID。對於 systemd 系統實例來說,則是 "0 " |
"%u " |
運行 systemd 用戶實例的用戶名稱。對於 systemd 系統實例來說,則是 "root " |
"%U " |
運行 systemd 用戶實例的用戶UID。對於 systemd 系統實例來說,則是 "0 " |
"%v " |
內核版本(uname -r 的輸出) |
"%V " |
存放大體積臨時文件以及持久臨時文件的目錄。也就是 /var/tmp 或 "$TMPDIR ", "$TEMP ", "$TMP " 之一(若已設置) |
"%% " |
百分號自身(%)。使用 "%% " 表示一個真正的 "% " 字符。 |
例子
例 1. 允許單元被啓用
下面這個 foo.service
單元中的 [Install] 小節表明該單元可以通過 systemctl enable 命令啓用。
[Unit] Description=Foo [Service] ExecStart=/usr/sbin/foo-daemon [Install] WantedBy=multi-user.target
執行 systemctl enable 啓用命令之後, 將會建立一個指向該單元文件的軟鏈接 /etc/systemd/system/multi-user.target.wants/foo.service
, 表示將 foo.service
包含到 multi-user.target
目標中, 這樣,當啓動 multi-user.target
目標時, 將會自動起動 foo.service
服務。 同時,systemctl disable 命令 將會刪除這個軟連接。
例 2. 覆蓋軟件包的默認設置
以例如 foo.type
這樣的系統單元爲例, 有兩種修改單元文件的方法: (1)將單元文件從 /usr/lib/systemd/system
目錄 複製到 /etc/systemd/system
目錄中, 然後直接修改複製後的副本。 (2)創建 /etc/systemd/system/foo.type.d/
目錄, 並在其中創建一些
文件, 然後 僅針對性的修改某些個別選項。name
.conf
第一種方法的優點是易於修改整個單元, 因爲原有的單元文件會被完全忽略。 但此種方法的缺點是, 當原有的單元文件被更新時, 變更不能在修改後的副本上自動體現出來。
第二種方法的優點是僅需修改個別選項, 並且原有單元文件的更新能夠自動生效。 因爲 .conf
文件只會按照其文件名的字典順序,被依次追加到原有單元文件的尾部。 但此種方法的缺點是原有單元文件的更新 有可能導致與 .conf
文件中的設置不兼容。
這同樣適用於 systemd 用戶實例, 只是用戶單元文件的文件系統位置不同而已。 參見前文的"單元目錄"小節。
下面是一個實例,假定原有的單元文件 /usr/lib/systemd/system/httpd.service
包含以下內容:
[Unit] Description=Some HTTP server After=remote-fs.target sqldb.service Requires=sqldb.service AssertPathExists=/srv/webserver [Service] Type=notify ExecStart=/usr/sbin/some-fancy-httpd-server Nice=5 [Install] WantedBy=multi-user.target
假定系統管理員想要修改幾個設置: (1)本地並不存在 /srv/webserver
目錄,需要修改爲 /srv/www
目錄。 (2)讓此服務依賴於本地已經存在的 memcached.service
服務(Requires=
), 且在其後啓動(After=
)。 (3)爲了加固此服務, 添加一個 PrivateTmp=
設置(參見 systemd.exec(5) 手冊)。 (4)將此服務的進程謙讓值重置爲默認值"0"。
第一種方法,將原有的單元文件複製到 /etc/systemd/system/httpd.service
並做相應的修改:
[Unit] Description=Some HTTP server After=remote-fs.target sqldb.service memcached.service Requires=sqldb.service memcached.service AssertPathExists=/srv/www [Service] Type=notify ExecStart=/usr/sbin/some-fancy-httpd-server Nice=0 PrivateTmp=yes [Install] WantedBy=multi-user.target
第二種方法, 創建配置片段 /etc/systemd/system/httpd.service.d/local.conf
並在其中填入如下內容:
[Unit] After=memcached.service Requires=memcached.service # 重置所有斷言,接着重新加入想要的條件 AssertPathExists= AssertPathExists=/srv/www [Service] Nice=0 PrivateTmp=yes
注意, 對於單元配置片段, 如果想要移除列表選項(例如 AssertPathExists=
或 ExecStart=
)中的某些項, 那麼必須首先清空列表(設爲空),然後才能添加(剔除掉某些項之後)剩餘的列表項。 注意,因爲依賴關係列表(After=
之類)不能被重置爲空,所以: (1)在配置片段(.conf
)中只能添加依賴關係; (2)如果你想移除現有的依賴關係,並重新設定, 那麼只能用第一種方法(先複製,然後直接修改複製後的副本)。