繁体   English   中英

如何在Linux上检测挂起的系统关闭?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM