现在,我试图弄清楚如何使自定义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之后订购。 br />
[Unit]
Wants=network-online.target
After=network.target network-online.target
用于服务的单位文件和systemd。
当前版本软件中的实现
现在,您需要确保
network-online.target
可以正常工作(或者至少可以使用network.target
)。当前版本的NetworkManager提供了
NetworkManager-wait-online.service
,它可以通过network-online.target
来获取,从而可以通过您的服务来获取。此特殊服务可确保您的服务将等待,直到配置为自动启动的所有连接自动成功,失败或超时。当前版本的systemd-networkd会阻塞您的服务,直到按照要求配置了所有设备。更为容易的是,它目前仅支持在引导时(更具体地说是`systemd-networkd.service的启动时)应用的配置。
为了完整起见,Fedora中的
/etc/init.d/network
服务,如当前systemd版本所解释的那样,阻止network.target
,从而间接阻止network-online.target
和您的服务。这是基于脚本的实现的一个示例。如果您的实现(无论是基于守护程序还是基于脚本)表现为上述网络管理服务之一,它将延迟您的服务启动,直到完成网络配置为止。成功完成,由于某种原因失败或在合理的时间范围后超时。
您可能需要检查netctl是否以相同的方式工作,并且该信息将对该答案有所帮助。
旧版本软件中的实现方式
我不认为您将看到systemd的版本足够旧,无法正常运行。但是您可以检查至少存在
network-online.target
,并在network.target
之后对其进行排序。以前,NetworkManager仅保证将应用至少一个连接。即使要使它正常工作,您也必须显式启用
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
之前订购自己。 /> [Unit]
Before=network.target
[Service]
Type=oneshot
ExecStart=...
RemainAfterExit=yes
即使不是很有用,基于守护程序的网络管理服务也应该在
network.target
之前先订购自己。[Unit]
Before=network.target
[Service]
Type=simple
ExecStart=...
等待守护程序完成的服务应在特定服务之后和
network-online.target
之前订购自己。它应在守护程序服务上使用network.target
,以便在未使用相应的网络管理服务的情况下立即失败。在network-online.target
目录中等待Requisite
的服务,以便希望等待已配置网络的服务将其拉入。[Unit]
Requisite=...
After=...
Before=network-online.target
[Service]
Type=oneshot
ExecStart=...
RemainAfterExit=yes
相关文档
http://www.freedesktop.org/software/systemd/man/systemd.special.html#network-online.target
http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/
最后的笔记
我希望我不仅能在您提出问题时帮助回答您的问题,而且有助于改善上游和Linux发行版的情况,以便我现在可以提供比编写原始版本时更好的答案。
评论
您是否通过“等待直到配置为自动启动的所有连接都成功”来表示自动连接选项?当我设置no-auto-default = *但在其中一个连接上具有autoconnect = yes时,可以利用此功能吗?最后一个问题-我不了解nm-online和手册页的--wait-for-startup选项没有太大帮助。感谢您的撰写,非常感谢!
–lzap
2015年11月11日,12:33
据我所知,nm-online不在乎无自动默认设置,仅在乎自动设置。您有什么具体问题吗?在我看来,nm-online联机帮助页明确指出,使用-s会等待尝试进行所有自动连接,即连接或失败。
– PavelŠimerda
2015年11月11日14:39
在处理了一个小时的废话之后,我找到了解决方案:apt-get install sysv-init。 :-) systemd取代了一些shell脚本而增加的复杂性令人难以置信。
– Mantriur
16-3-6在22:17
@Someone我担心在这种情况下initscripts无法解决问题。如果您使用的是NetworkManager或任何其他动态配置工具,则初始化脚本无法在完全配置的网络后对其进行排序。您可以使用/etc/init.d/network或类似工具来获得有限的动态配置,但这不能普遍使用。
– PavelŠimerda
16 Mar 23 '16 at 21:30
@PavelŠimerdaInit会串行执行,并且在完成后续脚本需要依靠的操作之前,不会返回正确的init脚本。对于网络,这意味着已准备好所有适用的适配器。除非是幸运的时机,否则NM在此情况下表现良好。当然,真正的问题是NM重塑了网络处理方式,而不是在现有的简单,久经考验的结构上进行构建。桌面人员似乎对复杂性的危险一无所知。 ;-)
– Mantriur
16 Mar 24 '16 at 15:21
#2 楼
您可以在After
部分中使用[Unit]
定义应在服务启动之前启动的服务。例如,如果您使用的是NetworkManager,则可以在启动NetworkManager之后启动服务。[Unit]
Description=test service
After=NetworkManager.service
评论
BindsTo在这里不太合适,因为该服务是一次性事件,而不是持久性服务(除非它还包括ExecStop功能,当网络中断时会触发)。
–金锁
14-4-22在18:23
删除BindsTo
–糟糕
2014年4月22日在18:24
如果您只想在NetworkManager运行服务时运行,则可以添加一些内容来替换BindsTo,例如Requires。之后实际上并没有执行此操作-仅表示NM是否也在运行,然后再运行。如果不打算运行NM,则该服务将在任意点运行。
–金锁
2014年4月22日在18:25
After = network.target比After = NetworkManager.service更好,因为它更通用。
– PavelŠimerda
2014年4月23日15:32
请注意,指定After = foo不会启动foo单元(如果尚未启动),它只会告诉systemd如果两个单元同时启动,则如何订购它们。如果没有启动,则同时使用After = foo和Wants = foo或Requires = foo将具有拉入foo的效果,并且还可以使systemd正确地对单元进行排序。
–埃米尔·伦德伯格(Emil Lundberg)
2014年8月12日在7:19
#3 楼
如果您的服务提供了一个服务器,该服务器可以被动地等待某人连接到该服务器,请使用以下服务器:[Unit]
After=network.target
您的服务应绑定在通配符接口上。如果它使用套接字激活(推荐),或者它是仅限本地的,则可以完全忽略网络目标。
如果您的服务充当客户端,或者是对等的,则更合适:
[Unit]
After=network-online.target
Requires=network-online.target
在systemd 213之前,network-online.target需要Pavel提到的解决方法(您需要手动启用将等待网络启动的服务)。从systemd 213开始,默认情况下会完成此操作。
systemd-networkd-wait-online
将等待至少一个地址(可路由或链接本地)在非环回接口上进行配置。配置systemd-networked,NetworkManager或等效功能是一项独立的任务。 DHCP(用于IPv4)和NDP(用于IPv6)往往开箱即用,但是您应该对其进行配置,以便您对“网络正常运行”的精确定义可以触发
network-online.target
。文档:
network.target
network-online.target
网络启动后运行服务
评论
很好奇为什么需要一个新的答案,而不仅仅是对现有的(希望)结构合理的答案进行小的改进。
– PavelŠimerda
2014-12-26 22:33
前两个文档链接当前已失效。
– Peter Hansen
15年3月2日在22:55
为什么使用Requires而不是Want?
–卡尔·莫里森(Karl Morrison)
17年8月9日在10:58
#4 楼
我想我可以通过弄乱WantedBy参数来更改脚本的运行点。
会产生与您想要的相反的效果。来自
man systemd.unit
:WantedBy =,RequiredBy =
[...]在每个目录的.wants /或.requires /目录中创建一个符号链接。
通过systemctl enable安装本机时列出的单元数。这样的效果是将列出的单元中的类型为Wants =
或Requires =的依赖项添加到当前单元中。
基于此,我们可以看到正确的单位选项是“想要”还是“需要”;根据这些描述,“ Requires”可能是正确的,加上“ After”以确保不仅可以运行网络服务,而且可以确保它在此单元之前运行。
单元选项AFAIK可以包括以下条件:启动的前提条件必须已经完成或达到某个点(联网可能是守护程序服务),但前提是必须先启动。考虑到这一点,您可能需要制作脚本
Type=forking
并抛出正常的延迟(例如30秒),或者某种包括延迟在内的成功退出循环,以确保首先拥有DHCP租约。 。评论
WantedBy和RequiredBy都不影响订购。
– PavelŠimerda
2014年4月23日在15:31
@PavelŠimerda:这里没有人声称他们这样做。排序是为什么我与Requires一起明确提到After之后,“不仅确保运行网络服务,而且确保它在此单元之前运行”。
–金锁
2014年4月24日12:45
是的,After以这种方式与Wants或Requires一起工作。另一方面,在基于依赖项的工具中,明确的延迟是个坏习惯,尤其是当有明确的方法要等到systemd文档指定网络配置后,因此,我不得不坚持不懈地投票。
– PavelŠimerda
2014年12月16日在12:07
#5 楼
使用After
部分中的[Unit]
来指定在您自己的服务之前应启动的内容。 (以上大部分答案是正确的。)要在网络建立后启动服务,请使用网络目标,无论您使用的是conf.d / netctl系统中的NetworkManager,都应使用网络目标。 Arch或systemd知道的其他服务。[Unit]
#.....
After=network.target
简要查看将确认系统上依赖网络连接的所有其他服务都包含此指令。
它也可以移植到使用systemd的任何发行版中。您的单位文件将与Arch,Fedora,RHEL 7,Debian的未来版本相同。
启动网络连接的服务(例如Arch的脚本或您自己的脚本)应请在各自的单位文件中指定。
[Unit]
Wants=network.target
Before=network.target
评论
我并不完全喜欢Wants部分,因为它对其他软件包有副作用。请看看我的回答。
– PavelŠimerda
2014年4月23日在15:41
刚刚意识到,在network.target上旺旺是个好主意。
– PavelŠimerda
2014年4月23日在15:52
您确实要使用network-online.target。参考
–爱德华·托瓦尔兹
15年10月31日在15:31
#6 楼
我想在本文中加一点。当前(2015年夏季)在RHEL7 / CentOS 7中,在IPv6网络启动之前,network-online.target设置不正确,因此,在服务定义中具有明确绑定到IPv6地址的操作可能会在IPv6启动并运行之前启动,从而导致它们失败。
评论
我想只有基于内核的IPv6自动配置才是这种情况,但无论如何还是有缺陷的。如果要在IPv6之后正确订购,则绝对应该使用NetworkManager代替/etc/init.d/network。如果即使使用NM也会遇到相同的问题,那么这是提出功能请求的一个很好的理由。我尚未与RHEL / CentOS核对过,如果您有兴趣,我可以为您提供详细信息。
– PavelŠimerda
16年4月18日在18:21
#7 楼
[Unit]
After=systemd-networkd.service
为我工作。
评论
不确定在某些特殊情况下是否可以使用,但出于几个原因它是错误的。其中之一是联网提供了自己的/ wait-online /服务。在network-online.target之后引入和排序是支持该服务的任何正确方法。
– PavelŠimerda
16年4月18日在18:17
评论
您也可以使用networkd-dispatcher