在Linux下,程序通过在崩溃处理程序中捕获exception(例如在段错误)来重启崩溃,最好的办法是什么?
你可以有一个循环,你基本上fork()
,在孩子中做真正的工作,然后等待孩子,并检查其父母的退出状态。 您也可以使用一个以类似的方式监控和重启程序的系统,比如daemontools,runit等等。
最简单的是
while [ 1 ]; do ./program && break; done
基本上,你运行程序,直到它返回0,然后你打破。
SIGSEGV
可以被捕获(见man 3 signal
或man 2 sigaction
),并且程序可以调用其中一个exec
系列函数来重启。 对于大多数运行时崩溃( SIGFPE
, SIGILL
, SIGBUS
, SIGSYS
,…)也是如此。
不过,在做这件事之前我会想一下。 对于unix程序来说,这是一个非常不寻常的策略,你可能会惊讶你的用户(不一定是愉快的方式)。
在任何情况下,如果在死亡之前有任何资源需要清理,请确保不要在SIGTERM
上自动重新启动,否则愤怒的用户将使用SIGKILL
并且会留下一团糟。
作为这里提出的补充:
另一个选择是像做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
进程无法自行重新启动,但是您可以使用像crontab(1)
这样的实用程序来安排脚本来检查进程是否仍然有效。
程序本身显然不应该检查它是否运行或不运行:)
大多数企业解决方案实际上只是一个奇怪的方法,从给定的字符串输入ps()
,然后在某些条件满足的情况下执行一个动作,即如果没有找到你的进程,则调用启动脚本。
如果它的具体到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) }