如何让我的用户服务等到网络上线?

如何让我的用户服务等到网络上线?

我编写了几个 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.targetnetwork-online.targetsystemd-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 linkfornetwork.targetnetwork-online.targetas 此处的其他建议,但我决定保持简单;)

请注意,尽管您创建了到系统服务的符号链接不是告诉您的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

相关内容