我编写了几个 systemd 用户服务文件,我希望用户启用这些文件,并且需要有效的网络连接。我认为这很简单:
Wants=network-online.target
After=network-online.target
然而,这些服务似乎开始得太早了,在journalctl
我看来:
network-online.target: Cannot add dependency job, ignoring: Unit network-online.target failed to load: No such file or directory.
然后我进行了更多搜索并尝试
Wants=network.target
After=network.target
并做到了sudo systemctl enable systemd-networkd-wait-online.service
。
现在我有journalctl
:
network.target: Cannot add dependency job, ignoring: Unit network.target failed to load: No such file or directory.
而且服务开始得太早了。
那条消息应该在那里吗?我该如何调试我的问题?
编辑: 原因很简单,具体说明在拱门维基:
systemd --user
作为独立于systemd --system
进程的进程运行。用户单位不能引用或依赖系统单位。
这个论坛帖子似乎提出了一个简单的解决方案:我应该link
作为用户提供必要的系统单元,从而在单元搜索路径上创建一个可用的符号链接。
这样做之后,我没有看到任何No such file or directory
消息,但是,在网络上线后我仍然无法使服务真正运行。我尝试过链接network.target
、network-online.target
和systemd-networkd-wait-online.service
,将我的单位设置为依赖于它们中的每一个,但没有成功。当我在用户模式下检查链接单元的状态时, 它们中的一些都已死亡,例如:
$ systemctl --user status network.target
● network.target - Network
Loaded: loaded (/usr/lib/systemd/system/network.target; linked; vendor preset: enabled)
Active: inactive (dead)
Docs: man:systemd.special(7)
http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget
$ systemctl status network.target
● network.target - Network
Loaded: loaded (/usr/lib/systemd/system/network.target; static; vendor preset: disabled)
Active: active since Sat 2015-07-18 19:20:11 MSK; 3h 35min ago
Docs: man:systemd.special(7)
http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget
Jul 18 19:20:11 calc-server systemd[1]: Reached target Network.
Jul 18 19:20:11 calc-server systemd[1]: Starting Network.
network-online.target
但是,链接后我可以在用户模式下看到活动状态:
$ systemctl --user status network-online.target
● network-online.target - Network is Online
Loaded: loaded (/usr/lib/systemd/system/network-online.target; linked; vendor preset: enabled)
Active: active since Sun 2015-07-19 00:35:38 MSK; 2min 48s ago
Docs: man:systemd.special(7)
http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget
Jul 19 00:35:38 calc-server systemd[469]: Reached target Network is Online.
Jul 19 00:35:38 calc-server systemd[469]: Starting Network is Online.
答案1
由于这个主题在谷歌搜索结果中排名第一,我为所有面临同样问题的人分享一个替代解决方案。
在我的系统中,我添加了一个简化的等效项/lib/systemd/system/systemd-networkd-wait-online.service
(即WantedBy=network-online.target
)并将其存储在用户服务目录中:
[Unit]
Description=User Wait for Network to be Configured
[Service]
Type=oneshot
ExecStart=/lib/systemd/systemd-networkd-wait-online
RemainAfterExit=yes
[Install]
WantedBy=default.target
然后我让我的用户服务依赖于这个新服务:
Wants=networkd-wait-online.service
After=networkd-wait-online.service
不过,Wants=
似乎不需要,因为WantedBy=default.target
.您可以删除WantedBy=default.target
,因此这成为network-wait-online.service
可选的,但您肯定需要Wants=network-wait-online.service
。
原始服务systemd-networkd-wait-online.service
包含更多依赖项,但它们似乎无法在用户上下文中工作。有人可能会为所有这些依赖项提供用户运行等效项,例如通过使用systemctl --user link
fornetwork.target
和network-online.target
as 此处的其他建议,但我决定保持简单;)
请注意,尽管您创建了到系统服务的符号链接不是告诉您的systemd --user
经理使用来自systemd --system
经理的一些事件来监视系统服务状态,但使其从用户上下文运行该服务的另一个实例。
答案2
既然你不能依赖系统服务,那么你唯一的解决方案就是提供一个检测网络是否在线的用户服务。 (或者使您的服务成为系统服务。)“在线检测”用户服务的详细信息将取决于您对“在线”的定义。例如,它可以等待 ping 8.8.8.8 成功。或者使 DNS 名称解析成功。例如,在 vpnc 的类似情况下,我等待对 vpn IP 的 ping 操作成功。
然后你可以让你的用户服务依赖于(After=)你的检测在线用户服务。
#!/bin/sh
host="${1:-8.8.8.8}"
pingcheck() {
ping -n -c 1 -w 5 $1 >/dev/null 2>&1
}
# Do you want a timeout ?
while :; do
pingcheck ${host} && exit 0
sleep 10
done
答案3
我建议测试这样的东西:
# /etc/systemd/system/foo.service
[Unit]
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/bin/logger -t foo "testing online target"
[Install]
WantedBy=multi-user.target
其次是:
# systemctl daemon-reload && systemctl enable foo.service