2012-02-06 13 views
0

申し訳ありませんので、私はデーモンとして動作しているC++で書かれたプログラムで作業しています。これは主にLinuxユーザーを対象としていますが、私はWindows(サービスとして実行中)とMacユーザーも含めたいと考えています。システム停止をC++で判断する

デーモンを手動でシャットダウンするたびにログに記録します。ただし、ではなく、システムの停止または再起動のためにシステムがログをシャットダウンする必要があります。

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

私の問題は、ランレベルはいつも私が期待するものではないということです。私はUbuntuを実行しています。いつものようにログインすると、ランレベル2になります。リブートするときも同じです。停止すると、時には "runlevel"からの出力として何も得られません。異なるLinuxディストリビューションは独自のランレベルを使用しているので、移植性には最適ではありません。

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

コードのスニペットをここに貼り付けます(ヘルプが必要な場合)。 Poco C++ librariesを使って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 
} 
+0

なぜあなたは 'SIGTERM'とシャットダウンされ、システム全体で終了しているあなたのサービスのために異なる動作を持っている必要がありますか? –

+0

それはプログラムの概念にある。常に実行することを意図しています。ただし、シャットダウンする必要がある場合は、特定の電子メールアドレスに報告する必要があります。私はいつもコンピュータが起動して再起動している間に統計情報を求めたくはありませんが、ユーザーが手動で中断したかどうかを判断したいと思います。これはちょっと意味があると思っています:) – roggan87

+0

自分のサーバー上でプログラムをアップグレードする(または使用しているデータベースを停止する!)場合は、「常に実行する」という考え方が異なるかもしれません。だから彼に彼のシステムを管理する能力を任せてください。 –

答えて

0

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

Linuxでの起動履歴を決定するために使用するコマンドは

$ last reboot 
関連する問題