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 |