如何检测Linux的关机/重启

11

我在我的C程序中尝试检测Linux的关机或重启。 我发现程序可以使用signal(SIGTERM, handler)和(SIGKILL, handler)。 但是如果用户用命令杀死进程,这两个也会被触发。

有些解决方案称可以使用runlevel,但它不起作用。 不知道进程是否在系统初始化runlevel之前被杀死。 我甚至尝试将脚本放置在rcx.d中,但仍然无法工作。

有人有建议吗? 我需要在许多种Linux系统上运行。

谢谢。

[更新] 我使用了R解决方案,但我仍然没有看到我的数据在重新启动或关闭时被清除。 是我的函数有问题吗?

int start() {
    if (initIni() == EXIT_FAILURE)
        return EXIT_FAILURE;
    struct sigaction act;
    memset(&act, '\0', sizeof(act));
    act.sa_sigaction = &signal_callback_handler;
    act.sa_flags = SA_SIGINFO;
    sigaction(SIGTERM, &act, NULL);
....
}

void signal_callback_handler(int signum, siginfo_t *siginfo, void *context) {
    if (signum == SIGTERM && (long)siginfo->si_pid == 1) {
        clearData();
    }
    exit(signum);
}

[更新] 最终,我使用了David Schwartz的runlevel(8) 示例 来解决我的问题。 如果您使用Linux命令runlevel将不会有用。 感谢提供这个好的解决方案。


1
你想如何处理这个关机/重启信号?比如说,重新启动进程? - versvs
硬件信号和软件信号之间有区别。 - Grijesh Chauhan
2
注意:SIGKILL无法被捕获! - isedev
可能是重复问题:如何从Linux应用程序检测关机/重启 - Paul R
我会使用信号来清除一些数据。 - sowrdking
可能是 如何检测 Linux 上的挂起系统关机? 的重复。 - tripleee
2个回答

7
您的假设是错误的。没有办法捕获SIGKILL信号;它终止进程,没有机会对其进行响应。
话虽如此,我可能有一个解决方案:您可以捕获SIGTERM信号,并且如果您使用sigaction安装信号处理程序并使用SA_SIGINFO标志,您应该能够确定哪个进程向您发送了SIGTERM信号。如果它来自init(pid 1),那么这是关机信号。这有点不正规但可能适用于您的目的。

你好,我尝试使用你的解决方案,但它仍然无法在关机时触发。请查看我上面的更新。谢谢。 - sowrdking

4
捕获SIGTERM信号。在处理程序中,读取/var/run/utmp文件以获取运行级别。参考runlevel(8)命令的源代码

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接