DAEMON(7) | daemon | DAEMON(7) |
NAME
daemon - 編寫與打包系統守護程序
描述
"守護程序"的意思是在後臺執行的服務程序, 常用於監督系統的執行或者提供某種功能。 在傳統的 SysV Unix 系統上, 多個守護程序必須嚴格按照特定的順序依次啟動。 在"新型"的 systemd(1) 系統上, 守護程序的啟動順序非常簡單且非常強大。 本手冊同時解說了上述兩種不同的啟動方案, 並特別推薦了應該包含在 systemd 系統中的守護程序。
傳統的SysV守護程序
傳統的SysV守護程序在啟動的時候, 應該在初始化階段執行下面的步驟:
注意,這些步驟對於下文講述的新型守護程序是不需要的, 除非為了刻意相容傳統的SysV系統。
新型守護程序
Linux 系統上的新型守護程序更容易被監控也更容易實現。
守護程序無需實現前文所描述的複雜步驟, 即可直接在 systemd 提供的乾淨的上下文環境中執行:
環境變數已經被清理、訊號處理器與訊號掩碼已經被重置、沒有遺留的檔案描述符、守護程序自動在其專屬的會話中執行、 標準輸入(STDIN)已被連線到 /dev/null 虛擬裝置(除非另有配置)、 標準輸出(STDOUT)與標準錯誤(STDERR)已被連線到 systemd-journald.service(8) 日誌服務(除非另有配置)、umask 已經被重置 ... 等等
新型守護程序只需要遵守如下要求:
上述要求與 Apple MacOS X Daemon Requirements[2] 類似, 但並不完全相同。
啟動
systemd 提供了多種啟動機制(見下文), 而服務單元也經常同時使用其中的幾種。 例如 bluetoothd.service 可以在插入藍芽硬體時被啟動, 也可以在某程序訪問其 D-Bus 介面時被啟動。 又如列印服務可以在IPP埠有流量接入時被啟動, 也可以在插入印表機硬體時被啟動, 還可以在有檔案進入印表機 spool 目錄時被啟動。 甚至對於必須在系統啟動時無條件啟動的服務, 為了儘可能併發啟動, 也應該使用某些啟動機制。 如果某守護程序實現了一個 D-Bus 服務或者監聽一個套接字, 那麼使用基於 D-Bus 或基於套接字的啟動機制, 將允許該程序與其客戶端同時並行啟動(從而加快啟動速度)。 因為所有的通訊渠道都已事先建立, 並且不會丟失任何客戶端請求, 同時 D-Bus 匯流排或者核心會將客戶端請求排入佇列等候, 直到完成啟動。
系統啟動時啟動
傳統的守護程序一般是在系統啟動時透過SysV初始化指令碼自動啟動, systemd 也支援這種啟動方式。
對於 systemd 來說, 如果希望確保某單元在系統啟動時自動啟動, 那麼最佳的做法是在預設啟動目標 (通常是 multi-user.target 或 graphical.target)的 .wants/ 目錄中為該單元建立軟連結。 參見 systemd.unit(5) 手冊以瞭解 .wants/ 目錄, 參見 systemd.special(7) 手冊以瞭解上述兩個特殊的啟動目標。
基於套接字的啟動
為了儘可能提高並行性與健壯性, 以及簡化配置與開發, 對於需要監聽套接字的服務, 強烈推薦使用基於套接字的啟動機制。 使用此機制後, 守護程序不再需要建立和繫結套接字, 而是由 systemd 接管這個工作。 systemd 將會根據單元檔案的設定, 預先建立所需的套接字, 並在第一個客戶端請求接入的時候啟動該服務, 以實現服務的按需啟動。 該機制的好處還在於, 預先建立好套接字之後, 所有使用此套接字通訊的程序可以並行啟動(包括客戶端和服務端)。 此外,重啟服務只會導致丟失最低限度的客戶端連線, 甚至不丟失任何客戶端請求 (例如對於 DNS 或 syslog 這樣的無狀態協議)。 因為套接字在服務重啟期間始終保持有效並且可被訪問, 同時所有客戶端請求也都被排入佇列等候處理。
使用此機制之後, 守護程序必須要從 systemd 接收已建立好的套接字, 而不能自己建立並繫結套接字。 關於如何使用該機制,參見 sd_listen_fds(3) 與 sd-daemon(3) 手冊。 只需要小小的修改, 即可在原有啟動機制的基礎上新增基於套接字的啟動機制, 至於如何移植,詳見後文。
systemd 透過 .socket 單元實現該機制,詳見 systemd.socket(5) 手冊。 必須確保所有為支援基於套接字啟動而建立的監聽 socket 單元都被包含在 sockets.target 中。 建議在 socket 單元的 "[Install]" 小節加入 WantedBy=sockets.target 設定, 以確保在啟用該單元時能夠自動新增上述依賴關係。 除非明確設定了 DefaultDependencies=no , 否則會為所有 socket 單元隱含的建立必要的順序依賴。 有關 sockets.target 的解釋,詳見 systemd.special(7) 手冊。 如果某 socket 單元已被包含在 sockets.target 中, 那麼不建議在其中再新增任何額外的依賴關係(例如 multi-user.target 之類)。
基於 D-Bus 的啟動
如果守護程序使用 D-Bus 與客戶端通訊, 那麼它應該使用基於 D-Bus 的啟動機制, 這樣當客戶端訪問其 D-Bus 介面時, 該服務將被自動啟動。 該機制是透過 D-Bus service 檔案實現的(不要與普通的單元檔案混淆)。 為了確保讓 D-Bus 使用 systemd 來啟動與維護守護程序, 必須在這些 D-Bus service 檔案中使用 SystemdService= 指明其匹配的服務單元。 例如,對於檔名為 org.freedesktop.RealtimeKit.service 的 D-Bus service 來說, 為了將其繫結到 rtkit-daemon.service 服務單元, 必須確保在該檔案中設定了 SystemdService=rtkit-daemon.service 指令。 注意,必須明確設定 SystemdService= 指令, 否則當服務單元同時使用多種啟動機制時, 可能會導致競爭條件的出現。
基於裝置的啟動
用於管理特定型別硬體的守護程序, 只應該在符合條件的硬體變為可用或者被插入時,才需要啟動。 為了達到上述目的, 可以將服務的啟動/停止與硬體的插入/拔出事件繫結。 當帶有 "systemd" 標籤的裝置出現在 sysfs/udev 裝置樹中時, systemd 將會自動為其建立對應的 device 單元。 透過向這些單元中新增對其他單元的 Wants= 依賴, 就可以實現當該 device 單元被啟動(也就是硬體被插入)時, 連帶啟動其他單元,從而實現基於裝置的啟動。 這可以透過向 udev 規則庫中新增 SYSTEMD_WANTS= 屬性來實現, 詳見 systemd.device(5) 手冊。 通常,並不是將 service 單元直接新增到裝置的 Wants= 依賴中, 而是透過專用的 target 單元間接新增。 例如,不是將 bluetoothd.service 新增到各種藍芽裝置的 Wants= 依賴中, 而是將 bluetoothd.service 新增到 bluetooth.target 的 Wants= 依賴中, 同時再將 bluetooth.target 新增到各種藍芽裝置的 Wants= 依賴中。 透過引入 bluetooth.target 這個抽象層, 系統管理員無需批次修改 udev 規則庫, 僅透過 systemctl enable|disable ... 命令 修改 bluetooth.target.wants/ 目錄中的軟連結, 即可控制 bluetoothd.service 的使用。
基於路徑的啟動
對於處理 spool 檔案或目錄的守護程序(例如列印服務)來說, 僅在 spool 檔案或目錄狀態發生變化或者內容非空時, 才需要啟動。 透過 .path 單元實現的、 基於路徑的啟動機制正好適用於這種場合, 詳見 systemd.path(5) 手冊。
基於定時器的啟動
對於週期性的操作(例如垃圾檔案清理或者網路對時), 可以透過基於定時器的啟動機制來實現。 這種機制透過 .timer 單元實現,詳見 systemd.timer(5) 手冊。
其他啟動方式
在其他作業系統上還存在著其他的啟動機制, 不過這些機制都可以被前述的各種機制的組合替代。 因此在這裡不再贅述。
與 SYSTEMD 整合
編寫 systemd 單元檔案
在編寫單元檔案時應當考慮下列建議:
安裝 service 單元檔案
當從原始碼編譯安裝(make install)軟體包時, 其中的系統服務單元檔案會被預設安裝到 pkg-config systemd --variable=systemdsystemunitdir 命令返回的目錄中(通常是 /usr/lib/systemd/system); 而其中的使用者服務單元檔案會被預設安裝到 pkg-config systemd --variable=systemduserunitdir 命令返回的目錄中(通常是 /usr/lib/systemd/user); 但並不應該使用 systemctl enable ... 命令啟用它們。 當從包管理器安裝(rpm -i)二進位制軟體包時, 其中的單元檔案應該同樣安裝到上述位置。 但不同之處在於, 還應該使用 systemctl enable ... 命令啟用它們, 因此安裝的單元有可能會在開機時自動啟動。
移植已有的守護程序
雖然 systemd 相容傳統的 SysV 初始化系統, 但是移植舊有的守護程序可以更好的利用 systemd 的先進特性。 建議對舊有的 SysV 守護程序做如下改進: ...[省略]...
放置守護程序的資料
建議遵守 file-hierarchy(7) 所建議的通用準則。
參見
systemd(1), sd-daemon(3), sd_listen_fds(3), sd_notify(3), daemon(3), systemd.service(5), file-hierarchy(7)
NOTES
- 1.
- LSB recommendations for SysV init scripts
- 2.
- Apple MacOS X Daemon Requirements
跋
本頁面中文版由中文 man 手冊頁計劃提供。
翻譯人員:金步國
金步國作品集:http://www.jinbuguo.com
中文 man
手冊頁計劃:https://github.com/man-pages-zh/manpages-zh
systemd 231 |