申し訳ありませんので、私はデーモンとして動作している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
}
なぜあなたは 'SIGTERM'とシャットダウンされ、システム全体で終了しているあなたのサービスのために異なる動作を持っている必要がありますか? –
それはプログラムの概念にある。常に実行することを意図しています。ただし、シャットダウンする必要がある場合は、特定の電子メールアドレスに報告する必要があります。私はいつもコンピュータが起動して再起動している間に統計情報を求めたくはありませんが、ユーザーが手動で中断したかどうかを判断したいと思います。これはちょっと意味があると思っています:) – roggan87
自分のサーバー上でプログラムをアップグレードする(または使用しているデータベースを停止する!)場合は、「常に実行する」という考え方が異なるかもしれません。だから彼に彼のシステムを管理する能力を任せてください。 –