Linux

使 systemd 使用者服務依賴於系統目標

  • March 15, 2016

我有這樣的使用者服務~/.config/systemd/user/example.service

[Unit]
Description=Example service
After=network.target

[Service]
ExecStart=/bin/bash -c 'host google.com > /var/tmp/example'

[Install]
WantedBy=default.target

當然,我試圖控制的實際服務實際上做了一些有用的事情並訪問了網路;這只是一個簡化的例子。

該服務通過它創建指向systemctl --user enable example.service的符號連結啟用。~/.config/systemd/user/default.target.wants/example.service``~/.config/systemd/user/example.service

使用此設置,並按照Arch Wikisystemd中的說明啟用使用者會話,該服務在啟動時以我的使用者身份啟動。但是,它實際上並沒有在網路建立後啟動;相反,它似乎立即開始,因為包含:/var/tmp/example

;; connection timed out; no servers could be reached

(而且我試圖控制的實際服務也無法訪問網路,並且由於類似的名稱查找錯誤而失敗)

這意味著該服務實際上並沒有在network.target. 如何讓它network.target在執行前等待?

忘記network.target. man systemd.special說:

network.target
       systemd automatically adds dependencies of type After for
       this target unit to all SysV init script service units
       with an LSB header referring to the $network facility.

因此,這個目標主要是 SysV 初始化腳本的兼容性黑客。

假設您的網路連接由 NetworkManager 處理,您當然可以正確地依賴此目標,因為NetworkManager.service定義了Before=network.target. 但這僅表示 NetworkManager 已經啟動,並不表示網路連接實際上已經建立。這可能需要一段時間(dhcp 往返、wifi 握手等),這完全是 NetworkManager 的工作。至少在我的系統(F18)上有一個名為NetworkManager-wait-online. 它使用nm-online實用程序進行阻塞,直到建立了活動連接。在您的單元定義中嘗試Require, Before這樣做或單獨使用該工具。

引用自:https://serverfault.com/questions/462138