我正在开发一个需要检测系统关闭的应用程序。 但是,我没有找到任何可靠的方式来获取此事件的通知。
我知道在关机时,我的应用会收到一个SIGTERM
信号,然后是SIGKILL
。我想知道是否有任何方法可以查询SIGTERM
是关闭序列的一部分?
有没有人知道是否有办法以编程方式查询(C API)?
据我所知,系统没有提供任何其他方法来查询即将发生的关机。如果是这样,那也可以解决我的问题。我一直在尝试runlevels
,但runlevels
的更改似乎是即时的,没有任何预先警告。
答案 0 :(得分:11)
也许有点晚了。是的,您可以通过调用运行级别命令来确定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
并比较文件中的差异。然后你应该知道如何做到这一点。
答案 1 :(得分:6)
无法确定SIGTERM
是否是关闭序列的一部分。要检测关闭序列,您可以使用ereOn和Eric Sepanson建议的使用rc.d
脚本,也可以使用DBus等机制。
但是,从设计的角度来看,忽略SIGTERM
是没有意义的,即使它不是关闭的一部分。 SIGTERM
的主要目的是礼貌地要求应用程序彻底退出,并且如果他/她不想要,则具有足够权限的人不太可能发出SIGTERM
应用退出。
答案 2 :(得分:5)
从男人关机:
如果使用时间参数,则在系统关闭前5分钟 创建
/etc/nologin
文件以确保进一步登录 不被允许。
所以你可以测试/etc/nologin
的存在性。它不是最佳的,但可能是最好的。
答案 3 :(得分:3)
使您的应用程序对某些SIGTERM信号的响应与其他信号不同似乎不透明且可能令人困惑。有争议的是,您应该始终以相同的方式响应给定的信号。添加异常条件会使理解和测试应用程序行为变得更加困难。
添加处理关闭的rc脚本(通过发送特殊信号)是处理此类问题的完全标准方法;如果此脚本作为标准软件包(make install
或rpm / deb打包)的一部分安装,则不必担心控制用户计算机。
答案 4 :(得分:2)
它有点像黑客,但如果服务器正在运行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没有为两个结果返回不同的退出代码。但它似乎相当可靠。但是,如果更新系统,则需要注意消息中的格式更改。
答案 5 :(得分:2)
我想我明白了。
来源= 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");
答案 6 :(得分:2)
请参阅man systemctl
,您可以确定系统是否正在关闭:
if [ "`systemctl is-system-running`" = "stopping" ]; then
# Do what you need
fi
这是bash,但你可以用C
中的'system'来做答案 7 :(得分:1)
当系统关闭时,将调用rc.d
脚本。
也许您可以在那里添加一个脚本,向您的程序发送一些特殊信号。
但是,我怀疑你可以通过这种方式停止系统关闭。
答案 8 :(得分:1)
执行你最初想要的实际答案是你检查关机过程(例如ps aux | grep“shutdown -h”)然后,如果你想确定你检查它的命令行参数和时间它启动(例如,在14:51开始的“shutdown -h +240”将在18:51关闭)。
在一般情况下,从整个系统的角度来看 ,没有办法做到这一点。 “关闭”可能有很多种不同的方式。例如,有人可以决定拔出插头以便在关机时硬件停止他们现在有坏/危险行为的程序,或者UPS可以先发送一个SIGHUP然后然后失败。由于这样的关闭可能突然发生,并且系统中没有任何警告,因此无法确定在SIGHUP之后继续运行是否正常。
如果一个进程收到SIGHUP,你基本上应该假设很快就会有更糟糕的东西。如果你想做一些特别的事情并部分忽略SIGHUP那么a)你需要协调它与任何程序将关闭和b)你需要准备,如果其他系统关闭并在SIGHUP后很快杀死你您的软件和数据将继续存在。写出您拥有的任何数据,并继续写入具有安全原子更新的仅附加文件。
对于您的情况,我几乎可以肯定您当前的解决方案(将所有SIGHUP视为关闭)是正确的方法。如果你想改进一些东西,你应该向关机程序添加一个功能,通过DBUS或类似的方式进行通知。