You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在RedHat系统中编程判断系统即将重启并区分信号触发原因?

Great question! Distinguishing between signals sent by system shutdown/reboot vs user-initiated termination is a common pain point, especially when you need to conditionally save state. Let's break down the solutions tailored for your Red Hat system, since RHEL uses different init systems depending on the version.


For RHEL 7+ (systemd-based systems)

Systemd creates a dedicated marker file when scheduling a shutdown or reboot, which is the most reliable way to distinguish system-initiated signals from user ones. Here's what you can do:

  1. Check the shutdown marker file: When systemd plans a reboot or poweroff, it creates /run/systemd/shutdown/scheduled. This file contains plaintext details like USEC=1700000000000 MODE=reboot (for reboot) or MODE=poweroff (for shutdown).
  2. In your signal handler: When your app receives SIGTERM or SIGHUP, check if this file exists and parse its content to confirm if a system shutdown/reboot is in progress.

Python Example

import signal
import os

def handle_system_signal(signum, frame):
    shutdown_marker = "/run/systemd/shutdown/scheduled"
    system_shutdown = False

    if os.path.exists(shutdown_marker):
        with open(shutdown_marker, "r") as f:
            content = f.read()
            if "MODE=reboot" in content or "MODE=poweroff" in content:
                system_shutdown = True

    if system_shutdown:
        print("System reboot/shutdown detected — saving application state...")
        # Add your state-saving logic here
    else:
        print("User-initiated termination — skipping state save.")
    exit(0)

# Register handlers for TERM and HUP signals
signal.signal(signal.SIGTERM, handle_system_signal)
signal.signal(signal.SIGHUP, handle_system_signal)

# Keep the app running (replace with your actual application logic)
while True:
    pass

C Example

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>

void handle_signal(int signum, siginfo_t *info, void *context) {
    int fd = open("/run/systemd/shutdown/scheduled", O_RDONLY);
    int is_system_shutdown = 0;

    if (fd != -1) {
        char buf[256];
        ssize_t read_bytes = read(fd, buf, sizeof(buf) - 1);
        if (read_bytes > 0) {
            buf[read_bytes] = '\0';
            if (strstr(buf, "MODE=reboot") || strstr(buf, "MODE=poweroff")) {
                is_system_shutdown = 1;
            }
        }
        close(fd);
    }

    if (is_system_shutdown) {
        printf("System reboot/shutdown detected — saving state...\n");
        // Add state-saving logic here
    } else {
        printf("User-initiated termination — no state save.\n");
    }
    exit(0);
}

int main() {
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_sigaction = handle_signal;
    sa.sa_flags = SA_SIGINFO;

    sigaction(SIGTERM, &sa, NULL);
    sigaction(SIGHUP, &sa, NULL);

    while (1) {
        pause();
    }
    return 0;
}

For RHEL 6 and older (SysVinit-based systems)

Older RHEL versions use SysVinit, which relies on runlevels to trigger shutdown/reboot:

  • Runlevel 0 = Shutdown
  • Runlevel 6 = Reboot

You can:

  1. Check if the system is transitioning to runlevel 0 or 6 using the runlevel command, or by reading the /var/run/utmp file directly.
  2. Verify the existence of the /var/run/shuttingdown marker file (created by some SysVinit implementations during shutdown).

Quick Bash Check (can be called from your app)

target_runlevel=$(runlevel | awk '{print $2}')
if [ "$target_runlevel" = "0" ] || [ "$target_runlevel" = "6" ]; then
    echo "System shutdown/reboot in progress"
else
    echo "User-initiated termination"
fi

Key Notes

  • Permissions: The marker files (/run/systemd/shutdown/scheduled and /var/run/shuttingdown) are world-readable, so even non-root apps can access them.
  • Timing: Systemd creates the shutdown marker before sending termination signals to services, so your signal handler will always see the file if the signal is system-initiated.
  • Edge Cases: Avoid relying solely on signal sender PID checks (e.g., checking if the sender is PID 1) — user-initiated signals via sudo kill can also trace back to PID 1, leading to false positives.

内容的提问来源于stack exchange,提问作者Mark Arnold

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 18:35:27