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

如何通过Launch Daemon判断macOS是否正在重启?

判断macOS重启状态(Launch Daemon场景)

对于运行在macOS上的C++编写的Launch Daemon,有几种可靠的方式判断系统是否正在重启/进入收尾阶段:

1. 监听系统级通知

macOS通过CoreFoundation框架提供系统状态变更通知,你可以在Daemon中注册监听com.apple.system.restart或com.apple.system.shutdown通知,这是最直接的触发式检测方式。

示例C++代码:

#include <CoreFoundation/CoreFoundation.h>

void restartNotificationCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
    // 回调触发时,系统已启动重启流程
    CFShow(CFSTR("System is restarting..."));
    // 在此执行你的收尾逻辑
}

int main() {
    CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter();
    CFNotificationCenterAddObserver(
        center,
        NULL,
        restartNotificationCallback,
        CFSTR("com.apple.system.restart"),
        NULL,
        CFNotificationSuspensionBehaviorDeliverImmediately
    );

    // 维持Daemon运行的事件循环
    CFRunLoopRun();
    return 0;
}

编译提示:需链接CoreFoundation框架,示例命令:g++ -o restart_monitor restart_monitor.cpp -framework CoreFoundation

2. 检查系统关机标志文件

系统进入重启/关机收尾阶段时,会自动创建/var/run/shuttingdown文件。你可以通过两种方式检测该文件:

方式A:轮询检查(简单易实现)

#include <fstream>
#include <unistd.h>

bool isSystemShuttingDown() {
    std::ifstream file("/var/run/shuttingdown");
    return file.good();
}

int main() {
    while(true) {
        if(isSystemShuttingDown()) {
            // 系统已进入重启/关机流程
            break;
        }
        sleep(1);
    }
    return 0;
}

方式B:kqueue监听(高效无轮询)

#include <sys/event.h>
#include <sys/stat.h>
#include <unistd.h>
#include <iostream>

int main() {
    int kq = kqueue();
    if(kq == -1) {
        perror("kqueue failed");
        return 1;
    }

    struct kevent event;
    EV_SET(&event, AT_FDCWD, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT, NOTE_WRITE | NOTE_ATTRIB, 0, "/var/run/shuttingdown");

    int nev = kevent(kq, &event, 1, NULL, 0, NULL);
    if(nev == -1) {
        perror("kevent failed");
        close(kq);
        return 1;
    }

    // 事件触发说明文件已创建,系统进入收尾阶段
    std::cout << "System is entering shutdown/restart phase" << std::endl;

    close(kq);
    return 0;
}

3. 捕获launchd发送的SIGTERM信号

系统准备重启/关机时,launchd会向所有Daemon发送SIGTERM信号,等待30秒后若进程未退出,会发送SIGKILL强制终止。你可以捕获该信号,再结合前两种方式确认是否为系统重启(避免误判launchd单独重启Daemon的情况)。

示例代码:

#include <signal.h>
#include <unistd.h>
#include <iostream>

volatile sig_atomic_t shutdown_flag = 0;

void sigtermHandler(int signum) {
    shutdown_flag = 1;
}

int main() {
    signal(SIGTERM, sigtermHandler);

    while(!shutdown_flag) {
        // 正常业务逻辑执行
        sleep(1);
    }

    // 收到信号后,可进一步验证系统状态
    std::cout << "Received SIGTERM, preparing for shutdown/restart" << std::endl;
    return 0;
}

额外注意事项

  • Launch Daemon以root权限运行,无需担心访问/var/run/shuttingdown的权限问题。
  • 若需执行长耗时收尾逻辑,可修改Daemon的plist配置文件,通过ExitTimeOut键延长launchd的等待时间(最长不超过300秒)。
  • 系统通知监听需要Daemon维持CFRunLoop运行,若已有自定义事件循环,可直接集成监听逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 12:40:30