我对 systemd 比较陌生,正在学习它的架构。
现在,我正在尝试找出如何运行自定义 shell 脚本。该脚本需要运行后网络层已经启动。
我正在运行 Arch,使用 systemd 和 netctl。
为了测试,我编写了一个简单的脚本,只执行ip addr list > /tmp/ip.txt
.我为此脚本创建了以下服务文件。
(/etc/systemd/system/test.service)
[Unit]
Description=test service
[Service]
ExecStart=/root/test.script
[Install]
WantedBy=multi-user.target
然后我启用了该脚本,
systemctl enable test
重新启动后,脚本确实会运行,但它会在网络启动之前运行。换句话说,输出ip.txt
显示没有分配给主接口的 IPv4 地址。当我登录时,IPv4 地址确实已分配并且网络已启动。
我猜我可以通过弄乱参数来改变脚本运行的点WantedBy
,但我不知道该怎么做。
有人能指出我正确的方向吗?
答案1
关于 systemd 网络配置依赖项
很容易影响 systemd 的单位排序。另一方面,您需要注意已完成的单元所保证的内容。
配置您的服务
在当前系统上,排序后network.target
仅保证网络服务已启动,而不是有一些实际配置。您需要在之后订购network-online.target
并将其拉入才能实现这一目标。
[Unit]
Wants=network-online.target
After=network-online.target
为了与旧系统兼容,您可能还需要在 network.target 之后订购。
[Unit]
Wants=network-online.target
After=network.target network-online.target
这是您的服务和 systemd 的单元文件。
在当前版本软件中的实现
现在您需要确保它network-online.target
按预期工作(或者您至少可以使用network.target
)。
当前版本网络管理器提供NetworkManager-wait-online.service
被您的服务所吸引network-online.target
并因此被您的服务所吸引的东西。此特殊服务可确保您的服务将等待,直到配置为自动启动的所有连接成功、失败或超时。
当前版本systemd-networkd阻止您的服务,直到所有设备均按要求配置。它更容易,因为它目前仅支持在启动时应用的配置(更具体地说是“systemd-networkd.service 的启动时间”)。
为了完整起见,/etc/init.d/network
Fedora 中的服务(由当前版本的 systemd 解释)会阻止network.target
,从而间接阻止network-online.target
您的服务。这是基于脚本的实现的示例。
如果您的实现(无论是基于守护程序还是基于脚本)表现为上述网络管理服务之一,它将延迟服务的启动,直到网络配置成功完成、因充分原因失败或在合理时间后超时框架来完成。
您可能想检查是否网络控制以同样的方式工作,该信息将是对此答案的有价值的补充。
旧版本软件中的实现
我认为您不会看到足够旧的 systemd 版本,因为它不能很好地工作。但您可以检查至少network-online.target
存在并且它在 后被排序network.target
。
之前网络管理器只保证至少有一个连接会被应用。即使要使其发挥作用,您也必须NetworkManager-wait-online.service
显式启用。这个问题在 Fedora 中早已得到修复,但最近才在上游应用。
systemctl enable NetworkManager-wait-online.service
关于network.target和network-online.target实现的注释
您不需要让您的软件依赖于NetworkManager.service
任何NetworkManager-wait-online.service
其他特定服务。相反,所有网络管理服务都应该在 之前network.target
并且可选地对自己进行排序network-online.target
。
一个简单的基于脚本的网络管理服务应该在退出之前完成网络配置,并且应该在之前对自己进行排序,network.target
从而间接地在退出之前进行排序network-online.target
。
[Unit]
Before=network.target
[Service]
Type=oneshot
ExecStart=...
RemainAfterExit=yes
基于守护进程的网络管理服务也应该先对自己进行排序,network.target
即使它不是很有用。
[Unit]
Before=network.target
[Service]
Type=simple
ExecStart=...
等待守护进程完成的服务应将自身排序在特定服务之后和之前network-online.target
。它应该Requisite
在守护程序服务上使用,以便在不使用相应的网络管理服务时它会立即失败。
[Unit]
Requisite=...
After=...
Before=network-online.target
[Service]
Type=oneshot
ExecStart=...
RemainAfterExit=yes
wants
该包应该在目录中安装一个指向等待服务的符号链接network-online.target
,以便它被想要等待配置网络的服务拉入。
ln -s /usr/lib/systemd/system/... /usr/lib/systemd/system/network-online.target.wants/
相关文档
- http://www.freedesktop.org/software/systemd/man/systemd.special.html#network-online.target
- http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/
最后的笔记
我希望我不仅在您提出问题时帮助回答您的问题,而且还为改善上游和 Linux 发行版的情况做出了贡献,以便我现在可以给出比撰写原始问题时更好的答案。
答案2
如果您的服务提供了一个服务器,它可以被动等待某人连接到它,请使用以下命令:
[Unit]
After=network.target
您的服务应该绑定在通配符接口上。如果它使用套接字激活(推荐),或者如果它只是本地的,您可以完全忽略网络目标。
如果你的服务充当客户端,或者是点对点的,那么这更合适:
[Unit]
After=network-online.target
Requires=network-online.target
之前系统213,network-online.target 需要 Pavel 提到的解决方法(您需要手动启用等待网络启动的服务)。从 systemd 213 开始,这是默认完成的。systemd-networkd-wait-online
将等待在非环回接口上配置至少一个地址(可路由或链路本地)。
配置 systemd-networkd、NetworkManager 或等效项是一项独立的任务。 DHCP(适用于 IPv4)和 NDP(适用于 IPv6)往往可以开箱即用,但您应该配置它们,以便触发“网络已启动”的精确定义network-online.target
。
文档:
答案3
您可以使用After
in[Unit]
部分来定义应在服务启动之前启动的服务。例如,如果您使用 NetworkManager,则可以让您的服务在 NetworkManager 启动后启动。
[Unit]
Description=test service
After=NetworkManager.service
答案4
After
在部分中使用[Unit]
来指定应在您自己的服务之前启动的内容。 (之前的答案大部分都是正确的。)
要在网络启动后启动服务,请使用网络目标,无论您使用 NetworkManager、Arch 中的 conf.d/netctl 系统还是 systemd 识别的其他服务,该目标都应该适用。
[Unit]
#.....
After=network.target
简单看一下就可以确认每个其他系统上依赖网络连接的服务包含此指令。
它还可以移植到任何使用 systemd 的发行版。对于 Arch、Fedora、RHEL 7、Debian 的未来版本...,您的单元文件将是相同的
服务内容有哪些开始网络连接,例如 Arch 的脚本或您自己的脚本,应该在他们自己的单元文件。
[Unit]
Wants=network.target
Before=network.target