在c++中确定系统停止

Determine system halt in c++

本文关键字:系统 c++      更新时间:2023-10-16

好吧,我正在编写一个用c++编写的程序,它作为守护进程运行。它主要针对Linux用户,但我希望包括Windows(作为服务运行)和Mac用户。

我希望守护进程在手动关闭时进行日志记录。但是,它不应记录系统因系统停止或重新启动而导致的关闭。

目前,我已经屏蔽了所有信号,并使用sigaction()实现了某种处理。在记录关闭之前,一个函数还检查系统的运行级别,如果是0,1 0r 6,则会省略记录。检查运行级别的方法是运行命令"runlevel"并处理输出。

我的问题是运行级别并不总是我所期望的。我运行的是Ubuntu,当像往常一样登录时,我处于运行级别2,重新启动时也是如此。当停止时,我有时从"runlevel"中得不到任何输出。不同的Linux发行版都使用自己的运行级别,所以它对于可移植性来说不是最佳的。

那么,有没有更好的方法来确定系统是否正在停止?此外,是否有更好的方法来捕捉中断,例如通过异常处理等?

如果这里有任何帮助的话,我会粘贴一段代码。用c++编写,使用Poco c++库。

void MainApplication::signalHandler(int sig) {
#if defined(POCO_OS_FAMILY_UNIX)
    switch(sig) {
        case -1:
            struct sigaction act;
            act.sa_handler = signalHandler;
            sigemptyset(&act.sa_mask);
            act.sa_flags = 0;
            sigaction(SIGINT, &act, 0); //Better way to do this?
            sigaction(SIGQUIT, &act, 0);
            sigaction(SIGKILL, &act, 0);
            sigaction(SIGTERM, &act, 0);
            sigaction(SIGHUP, &act, 0);
            sigaction(SIGSTOP, &act, 0);
            sigaction(SIGTSTP, &act, 0);
            sigaction(SIGCONT, &act, 0);
            sigaction(SIGUSR1, &act, 0);
            sigaction(SIGUSR2, &act, 0);
            break;
        case SIGINT:
        case SIGQUIT:
        case SIGTSTP:
        case SIGHUP:
        case SIGKILL:
        case SIGTERM:
            //Log Shutdown!
            if (!isHalting())
                _instance->_database->logBypass(BYPASS_SHUTDOWN);
            terminateNicely(true);
            break;
        case SIGCONT:
            //Continued, means stopped
            break;
        case SIGUSR1:
            //Resetting Net Responsibility
            _instance->uninitialize();
            _instance->initialize(*_instance);
            break;
        case SIGUSR2:
            //Other action or just mask it
            break;
        default:
            //Caught signal
            break;
    }
#endif
}

bool MainApplication::isHalting() {
#if defined(POCO_OS_FAMILY_UNIX)
    string cmd("runlevel");
    vector<string> args;
    Poco::Pipe outPipe;
    ProcessHandle ph = Process::launch(cmd, args, 0, &outPipe, 0);
    ph.wait();
    Poco::PipeInputStream istr(outPipe);
    stringstream ss;
    Poco::StreamCopier::copyStream(istr, ss);
    int runlevel;
    ss.seekg(-2, ios::end);
    ss >> runlevel;
    return (runlevel == 0 || runlevel == 1 || runlevel == 6);
#else
    return false;
#endif
}

我最终走了另一条路来解决这个问题。现在我正在读取计算机的启动历史记录,并将其与软件的历史记录进行比较,看看计算机是在没有软件的情况下启动还是停止。这已经足够了,而且可能会更加准确。

用于确定Linux中引导历史记录的命令是

$ last reboot