使系统用户服务取决于系统目标

我在~/.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 

当然,我试图控制的实际服务确实有用,并访问了networking。 这只是一个简单的例子。

该服务通过systemctl --user enable example.servicesystemctl --user enable example.service ,它创build了指向~/.config/systemd/user/example.service的symlink〜 ~/.config/systemd/user/default.target.wants/example.service ~/.config/systemd/user/example.service

通过这个设置,以及Arch维基上描述的systemd用户会话,服务以启动时的用户身份启动。 但是,networkingbuild立后并没有真正启动, 相反,它似乎立即开始,因为/var/tmp/example包含:

 ;; connection timed out; no servers could be reached 

(而且,我试图控制的实际服务也无法到达networking,并且出现类似的名称查找错误)

这意味着该服务实际上不会在network.target之后运行。 如何在运行前等待network.target

忘掉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. 

所以,这个目标主要是针对SysV init脚本的兼容性攻击。

假设您的networking连接由NetworkManager处理,您当然可以依赖此目标,因为NetworkManager.service定义了Before=network.target 。 但这只意味着NetworkManager已经启动,而不是networking连接实际build立。 这可能需要一段时间(DHCP往返,无线握手等),完全是NetworkManager的业务。 至less在我的系统(F18)上有一个叫做NetworkManager-wait-online 。 它使用nm-online应用程序阻塞,直到build立活动连接。 在单元定义Require, Before尝试Require, Before或者单独使用该工具。

我遇到了同样的问题,需要访问互联网的用户级备份脚本。 我通过添加~/.config/systemd/user/wait-for-network.service来解决它,只需ping到google.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 

然后,我使得我的备份脚本依赖于它:

 [Unit] Description=... Requires=wait-for-network.service After=wait-for-network.service 

无论您是使用NetworkManager还是其他一些方式来build立连接,这都是有效的。