[英]How to detect pending system shutdown on Linux?
我正在开发一个需要检测系统关闭的应用程序。 但是,我没有找到任何可靠的方式来获取此事件的通知。
我知道在关机时,我的应用程序将收到SIGTERM
信号,然后是SIGKILL
。 我想知道是否有任何方法可以查询SIGTERM
是否是关闭序列的一部分 ?
有没有人知道是否有办法以编程方式查询(C API)?
据我所知,系统没有提供任何其他方法来查询即将发生的关机。 如果是这样,那也可以解决我的问题。 我也一直在尝试runlevels
,但runlevels
变化似乎是即时的,没有任何预先警告。
也许有点晚了。 是的,您可以通过调用runlevel命令来确定SIGTERM是否处于关闭过程中。 例:
#!/bin/bash
trap "runlevel >$HOME/run-level; exit 1" term
read line
echo "Input: $line"
将它保存为term.sh
并运行它。 通过执行killall term.sh
,您应该能够查看和调查主目录中的run-level
文件。 通过执行以下任何一项:
sudo reboot
sudo halt -p
sudo shutdown -P
并比较文件中的差异。 然后你应该知道如何做到这一点。
无法确定SIGTERM
是否是关闭序列的一部分。 要检测关闭序列,您可以使用像ereOn和Eric Sepanson建议的使用rc.d
脚本或使用DBus等机制。
但是,从设计的角度来看,忽略SIGTERM
是没有意义的,即使它不是关闭的一部分。 SIGTERM
的主要目的是礼貌地要求应用程序干净地退出,如果他/她不希望应用程序退出,则具有足够权限的人不太可能发出SIGTERM
。
从男人关机:
如果使用time参数,则在系统关闭前5分钟创建
/etc/nologin
文件以确保不允许进一步登录。
所以你可以测试/etc/nologin
存在。 它不是最佳的,但可能是最好的。
使您的应用程序对某些SIGTERM信号的响应与其他信号不同似乎不透明且可能令人困惑。 有争议的是,您应该始终以相同的方式响应给定的信号。 添加异常条件会使理解和测试应用程序行为变得更加困难。
添加处理关闭的rc脚本(通过发送特殊信号)是处理此类问题的完全标准方法; 如果此脚本作为标准软件包( make install
或rpm / deb打包)的一部分安装,则不必担心控制用户计算机。
它有点像黑客,但如果服务器正在运行systemd,如果你可以运行
/bin/systemctl list-jobs shutdown.target
......它会报告......
JOB UNIT TYPE STATE
755 shutdown.target start waiting <---- existence means shutting down
1 jobs listed.
...如果服务器正在关闭或重新启动(提示:如果你想专门查看它,那么有一个reboot.target)
你将No jobs running.
如果它没有被关闭。
你必须解析输出有点乱,因为systemctl没有为两个结果返回不同的退出代码。 但它似乎相当可靠。 但是,如果更新系统,则需要注意消息中的格式更改。
我想我明白了。
来源= https://github.com/mozilla-b2g/busybox/blob/master/miscutils/runlevel.c
我在这里复制部分代码,以防引用消失。
#include "libbb.h"
...
struct utmp *ut;
char prev;
if (argv[1]) utmpname(argv[1]);
setutent();
while ((ut = getutent()) != NULL) {
if (ut->ut_type == RUN_LVL) {
prev = ut->ut_pid / 256;
if (prev == 0) prev = 'N';
printf("Runlevel: prev=%c current=%c\n", prev, ut->ut_pid % 256);
endutent();
return 0;
}
}
puts("unknown");
请参阅man systemctl
,您可以确定系统是否正在关闭,如下所示:
if [ "`systemctl is-system-running`" = "stopping" ]; then
# Do what you need
fi
这是bash,但你可以用C中的'system'来做
系统关闭时,将调用rc.d
脚本。
也许您可以在那里添加一个脚本,向您的程序发送一些特殊信号。
但是,我怀疑你可以通过这种方式停止系统关闭。
做你最初想要的实际答案就是检查关机过程(例如ps aux | grep“shutdown -h”)然后,如果你想确定你检查它的命令行参数和启动时间(例如,在14:51开始的“shutdown -h +240”将在18:51关闭。
在一般情况下, 从整个系统的角度来看,没有办法做到这一点。 “关闭”可能有很多种不同的方式。 例如,有人可以决定拔出插头以便在关机时硬件停止他们现在有坏/危险行为的程序,或者UPS可以先发送一个SIGHUP然后然后失败。 由于这样的关闭可能突然发生并且系统中没有任何警告,因此没有办法确定在SIGHUP之后继续运行是可以的。
如果一个进程收到SIGHUP你应该基本上假设很快就会有更糟糕的东西。 如果你想做一些特别的事情并部分忽略SIGHUP那么a)你需要协调它与任何程序将关闭和b)你需要准备,如果其他系统关闭并在SIGHUP后很快杀死你您的软件和数据将继续存在。 写出您拥有的任何数据,并继续写入具有安全原子更新的仅附加文件。
对于您的情况,我几乎可以肯定您当前的解决方案(将所有SIGHUP视为关闭)是正确的方法。 如果你想改进一些东西,你应该向关机程序添加一个功能,它通过DBUS或类似的东西进行通知。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.