在网络关闭之前关机时运行脚本

在网络关闭之前关机时运行脚本

我想在我的计算机(Ubuntu 22.04)关闭但网络仍然可用时运行一个脚本。

中的建议此主题很有帮助地解释了如何创建一个在关机时运行的 systemd 服务文件,并且该脚本确实运行了,但是该脚本无法完成需要访问网络的任务,所以我认为网络已经关闭。

如果发现各种线程(例如这个) 关于如何确保脚本在网络关闭之前运行,但它们似乎都有略有不同的建议。我尝试了 Before=network-online.target、After=network-online.target 和 Requires=network-online.target 的各种排列,但似乎都没有用。

有人知道如何确保脚本可以在网络仍然可用时运行吗?

顺便说一句,我并不执着于用 systemd 来完成这项工作。我认为这是最好的方法,但如果有其他方法可以实现同样的效果,那就更好了。

答案1

不知道这是否有帮助,但请考虑查看 systemd .target 文件。这是 systemd 在关闭时实际运行的内容。这是一个链接。

https://documentation.suse.com/smart/linux/html/reference-managing-systemd-targets-systemctl/index.html

shutdown.target
       A special target unit that terminates the services on system
       shutdown.

       Services that shall be terminated on system shutdown shall add
       Conflicts= and Before= dependencies to this unit for their service
       unit, which is implicitly done when DefaultDependencies=yes is set
       (the default).

.target 文件与 .service 文件共存/usr/lib/systemd/system。如果是我,我会在虚拟机上执行此操作,这样我可以轻松回滚快照 ;)

答案2

好的,我又做了一些尝试,也取得了进展,但实际上还没有解决问题。

事实证明,如果我在服务文件中设置 After=network.target,网络确实可以正常工作。似乎是名称解析不起作用。因此,如果我运行与远程计算机的交互并指定远程计算机的主机名,则它不起作用,但如果我使用其 IP 地址指定它,则它确实可以工作。

我曾希望可以通过 After=network.target nss-lookup.target 来解决这个问题,但是这并没有解决问题。

还有什么想法我还可以尝试吗?

答案3

从我年迈而秃顶的头脑来看,为什么不编写一个 bash 脚本呢:

#!/bin/bash
Your Commands;
shutdown -h now

在“您的命令”执行完毕之前,不应执行关机。

该脚本可以被称为“myshutdown”,甚至可以别名为系统命令。

(对我来说这似乎过于简单了,我相信有人会指出我的错误!)(感谢“Marco”对代码进行整理)

答案4

了解如何在网络中断之前让服务停止的关键是知道关机顺序是启动顺序的逆序。因此,您的服务应该启动 network-online.target同时还依赖于network-online.target,因为它需要网络处于开启状态。此外,还有ExecStart=ExecStop=操作可供您定义。由于您希望脚本在关机时(即服务停止时)运行,因此您需要定义ExecStop=指向脚本的 。

要进行设置,请执行以下操作:

  • 在里面[单元]部分,创建Requires=network-online.target依赖项
  • 将顺序设置为After=network-online.target
  • 在里面[服务]部分,不要定义ExecStart=动作。
  • 设置RemainAfterExit=true,因为我们没有创建ExecStart=动作。
  • 最后,创建一个ExecStop=指向您的脚本的动作,例如ExecStop=/home/username/bin/testscript.sh

记住,关机顺序是启动顺序的逆序。因此,当您的服务停止时,您放置在中的脚本ExecStop=将会运行。而且因为我们启动了此服务 network-online.target,它将被关闭所有服务都已network-online.target关闭。

举个例子...

这是一个用于获取您的公共 IP 地址的简单测试脚本curl。因此,需要 DNS 才能正常运行。

#!/bin/bash

# NAME: testscript.sh
# PATH: /home/username/bin

NOW=`date`
IP=`curl -s https://ipinfoio/ip`

echo $NOW $IP >> /home/username/ipaddresses

接下来,在 中创建一个 systemd 服务/单元文件/etc/systemd/system。我将其命名为testservice.service

[Unit]
Description:Test service to execute at shutdown prior to losing network
Requires=network-online.target
After=network-online.target

[Service]
Type=oneshot
RemainAfterExit=true
ExecStop=/home/username/bin/testscript.sh

[Install]
WantedBy=multi-user.target

告诉 systemd 读取我们的文件:

sudo systemctl daemon-reload

启用服务:

sudo systemctl enable testservice.service

然后重新启动系统,您将看到该文件/home/username/ipaddress将使用关机时的时间戳和您的公共 IP 地址进行更新。

相关内容