24

我正在开发一个需要检测系统关闭的应用程序。但是,我还没有找到任何可靠的方法来获取有关此事件的通知。

我知道在关机时,我的应用程序会收到一个SIGTERM信号,然后是SIGKILL. 我想知道是否有任何方法可以查询 aSIGTERM是否是关机序列的一部分

有谁知道是否有办法以编程方式查询(C API)?

据我所知,系统没有提供任何其他方法来查询即将关闭的情况。如果是这样,那也可以解决我的问题。我也一直在尝试runlevels,但变化runlevels似乎是瞬间的,没有任何事先警告。

4

9 回答 9

11

也许有点晚了。是的,您可以通过调用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

并比较文件中的差异。然后你应该知道如何去做。

于 2013-11-27T02:38:29.893 回答
6

无法确定 aSIGTERM是否是关闭序列的一部分。要检测关机顺序,您可以使用rc.dereOn 和 Eric Sepanson 建议的脚本,也可以使用 DBus 等机制。

但是,从设计的角度来看,SIGTERM即使它不是关闭的一部分,也没有必要忽略它。SIGTERM的主要目的是礼貌地要求SIGTERM应用程序干净地退出,如果他/她不希望应用程序退出,则具有足够权限的人不太可能发出 a 。

于 2010-05-20T05:14:43.117 回答
6

从人关机:

如果使用时间参数,则在系统关闭前 5 分钟/etc/nologin创建文件以确保不允许进一步登录。

所以你可以测试/etc/nologin. 它不是最优的,但可能是你能得到的最好的。

于 2011-11-02T09:43:24.323 回答
5

它有点黑客但如果服务器正在运行 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 不会为两个结果返回不同的退出代码。但它看起来确实相当可靠。但是,如果您更新系统,则需要注意消息中的格式更改。

于 2016-02-17T15:51:44.947 回答
3

使您的应用程序对某些 SIGTERM 信号的响应与其他信号不同似乎是不透明的并且可能会令人困惑。有争议的是,您应该始终以相同的方式响应给定的信号。添加异常条件会使理解和测试应用程序行为变得更加困难。

添加处理关闭的 rc 脚本(通过发送特殊信号)是处理此类问题的完全标准方法;如果此脚本作为标准包(make install或 rpm/deb 包)的一部分安装,则无需担心用户机器的控制。

于 2010-05-14T15:12:52.693 回答
3

我想我明白了。

来源 = 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");
于 2016-07-17T18:43:13.747 回答
3

看到man systemctl,您可以确定系统是否正在关闭,如下所示:

if [ "`systemctl is-system-running`" = "stopping" ]; then
    # Do what you need
fi

这是在 bash 中,但你可以用 C 中的 'system' 来做

于 2017-01-13T13:11:38.070 回答
2

做你最初想要的实际答案是检查关闭过程(例如 ps aux | grep "shutdown -h" ),然后,如果你想确保检查它的命令行参数和它的启动时间(例如,从 14:51 开始的“shutdown -h +240”将在 18:51 关闭)。

在一般情况下,从整个系统的角度来看,没有办法做到这一点。有许多不同的方式可以发生“关闭”。例如,有人可以决定拔掉插头以硬停止他们现在在关机时有不良/危险行为的程序,或者 UPS 可以先发送 SIGHUP 然后简单地失败。由于这种关闭可能会突然发生并且在系统中的任何地方都没有任何警告,因此无法确定在 SIGHUP 之后继续运行是可以的。

如果一个进程收到 SIGHUP,你基本上应该假设一些更糟糕的事情很快就会出现。如果您想做一些特殊的事情并部分忽略 SIGHUP,那么 a)您需要与任何将关闭的程序进行协调,并且 b)您需要做好准备,如果其他系统关闭并在 SIGHUP 后很快杀死您您的软件和数据将继续存在。写出您拥有的任何数据,并仅继续写入具有安全原子更新的仅附加文件。

对于您的情况,我几乎可以肯定您当前的解决方案(将所有 SIGHUP 视为关闭)是正确的方法。如果你想改进一些东西,你可能应该在关闭程序中添加一个功能,它通过DBUS或类似的东西进行通知。

于 2016-09-20T22:44:27.203 回答
1

当系统关闭时,将rc.d调用脚本。

也许您可以在那里添加一个脚本,向您的程序发送一些特殊信号。

但是,我怀疑您是否可以通过这种方式停止系统关闭。

于 2010-05-14T07:20:48.637 回答