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
在运行前等待?
我遇到了同样的问题,需要访问互联网的用户空间备份脚本。我通过添加~/.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
还是其他方式建立连接,这都有效。
忘记了network.target
。man systemd.special
说:
Run Code Online (Sandbox Code Playgroud)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
在您的单位定义中进行此操作或单独使用该工具。