使 systemd 用户服务依赖于系统目标

dfl*_*str 9 linux service arch-linux systemd

我有一个~/.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
Run Code Online (Sandbox Code Playgroud)

当然,我试图控制的实际服务确实做了一些有用的事情并访问网络;这只是一个简化的例子。

该服务是通过systemctl --user enable example.service它创建~/.config/systemd/user/default.target.wants/example.service指向的符号链接启用的~/.config/systemd/user/example.service

使用此设置,并systemd按照Arch Wiki 中所述启用用户会话,服务在启动时以我的用户身份启动。但是,实际上并没有在网络建立之后启动;相反,它似乎立即开始,因为/var/tmp/example包含:

;; connection timed out; no servers could be reached
Run Code Online (Sandbox Code Playgroud)

(而且我试图控制的实际服务也无法访问网络,并因类似的名称查找错误而失败)

这意味着该服务实际上并不在network.target. 我如何让它network.target在运行前等待?

Tho*_*mas 9

我遇到了同样的问题,需要访问互联网的用户空间备份脚本。我通过添加~/.config/systemd/user/wait-for-network.service只是 pinggoogle.com直到可以访问来解决它:

[Unit]
Description=Ping a server on the internet until it becomes reachable

[Service]
Type=oneshot
ExecStart=/bin/bash -c 'while ! ping -c1 google.com; do sleep 1; done'
TimeoutStartSec=60s
Run Code Online (Sandbox Code Playgroud)

然后我让我的备份脚本像这样依赖它:

[Unit]
Description=...
Requires=wait-for-network.service
After=wait-for-network.service
Run Code Online (Sandbox Code Playgroud)

无论您是使用NetworkManager还是其他方式建立连接,这都有效。


Sec*_*coe 3

忘记了network.targetman 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.
Run Code Online (Sandbox Code Playgroud)

因此,这个目标主要是 SysV 初始化脚本的兼容性破解。

假设您的网络连接由 NetworkManager 处理,您依赖此目标当然是正确的,因为NetworkManager.service定义了Before=network.target. 但这仅仅意味着NetworkManager已经启动,并不意味着网络连接真正建立起来。这可能需要一段时间(dhcp 往返、wifi 握手等),并且完全是 NetworkManager 的工作。至少在我的系统(F18)上有一个名为 的服务NetworkManager-wait-online。它使用nm-online实用程序进行阻塞,直到建立活动连接为止。尝试Require, Before在您的单位定义中进行此操作或单独使用该工具。