Linux では、プログラムがクラッシュ時にクラッシュ ハンドラー (セグメンテーション フォールトなど) で例外をキャッチして再起動するための最良の方法は何でしょうか?
7 に答える
最も簡単なのは
while [ 1 ]; do ./program && break; done
基本的には return 0 になるまでプログラムを実行してからブレークします。
SIGSEGV
キャッチすることができ (man 3 signal
またはを参照man 2 sigaction
)、プログラムはexec
再起動するためにそれ自体で関数ファミリの 1 つを呼び出すことができます。同様に、ほとんどのランタイム クラッシュ ( SIGFPE
、SIGILL
、SIGBUS
、SIGSYS
...)。
ただし、これを行う前に少し考えます。これは、UNIX プログラムではかなり珍しい戦略であり、ユーザーを驚かせる可能性があります (必ずしも楽しい方法ではありません)。
いずれにせよ、死ぬ前にクリーンアップしたいリソースがある場合は、自動再起動しないようにしてください。そうしないと、怒っているユーザーが使用して混乱を招くことになります。SIGTERM
SIGKILL
fork()
基本的に、子で実際の作業を行い、子を待って親で終了ステータスを確認するループを作成できます。同様の方法でプログラムを監視および再起動するシステム (daemontools、rinit など) を使用することもできます。
ここで提案されたものを補完するものとして:
もう1つのオプションは、gettyデーモンの場合と同じようにすることです。/ etc / inittabおよび適切なinittab(5)のマニュアルページを参照してください。それは最もシステム全体の平均であるようです;-)。
以下のファイルフラグメントのようになります。この意味の明らかな利点はかなり標準的であり、実行レベルを通じてデーモンを制御することができます。
# Run gettys in standard runlevels
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
segfault に固有の場合は、次のコードを試してください。これは、必要に応じて変更できます。
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include <poll.h>
sigjmp_buf buf;
void handler(int sig) {
siglongjmp(buf, 1);
}
int main() {
//signal(SIGINT, handler);
//register all signals
struct sigaction new_action, old_action;
new_action.sa_handler = handler;
sigemptyset (&new_action.sa_mask);
new_action.sa_flags = 0;
sigaction (SIGSEGV, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction (SIGSEGV, &new_action, NULL);
if (!sigsetjmp(buf, 1)){
printf("starting\n");
//code or function/method here
}
else{
printf("restarting\n");
//code or function/method here
}
while(1) {
poll(NULL,0,100); //ideally use usleep or nanosleep. for now using poll() as a timer
printf("processing...\n");
}
return 0; //or exit(SUCESS)
}
プロセス自体を再起動することはできませんがcrontab(1)
、スクリプトをスケジュールするなどのユーティリティを使用して、プロセスがまだ生きているかどうかを定期的に確認できます。
プログラム自体は、実行中か実行中でないかを明らかにチェックすべきではありません:)
ps()
ほとんどのエンタープライズ ソリューションは、実際には、特定の文字列の出力を grep し、特定の基準が満たされた場合にアクションを実行する、つまり、プロセスが見つからない場合は、開始スクリプトを呼び出すという手の込んだ方法です。