0

了解しました。デーモンとして実行されているC++で記述されたプログラムに取り組んでいます。これは主にLinuxユーザーを対象としていますが、Windows(サービスとして実行)とMacユーザーも含めたいと思います。

デーモンが手動でシャットダウンされるたびにログに記録するようにしたい。ただし、システムの停止または再起動のためにシステムによって行われたシャットダウンをログに記録しないでください。

現在、私はすべてのシグナルをマスクし、sigaction()を使用してある種の処理を実装しました。シャットダウンをログに記録する前に、関数はシステムのランレベルもチェックしており、それが0、1 0r 6の場合、ログは省略されます。ランレベルを確認する方法は、コマンド「runlevel」を実行して出力を処理することです。

私の問題は、ランレベルが必ずしも私が期待するものではないということです。私はUbuntuを実行しており、通常どおりログインするとランレベル2になります。これは、再起動しても同じです。停止すると、「ランレベル」からの出力として何も得られないことがあります。さまざまなLinuxディストリビューションが独自のランレベルを使用しているため、移植性には最適ではありません。

では、システムが停止しているかどうかを判断するためのより良い方法はありますか?また、例外処理などを介して、中断をキャッチするためのより良い方法はありますか?

ここで役立つ場合は、コードのスニペットを貼り付けます。PocoC ++ライブラリを使用して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
}
4

1 に答える 1

0

私は問題を解決するために別のルートに行くことになりました。ここで、コンピューターの起動履歴を読み取り、それをソフトウェアの履歴と比較して、コンピューターがソフトウェアなしで起動または停止したかどうかを確認します。それで十分であり、おそらくさらに正確になるでしょう。

Linuxで起動履歴を確認するために使用されるコマンドは次のとおりです。

$ last reboot
于 2012-06-28T07:10:19.963 に答える