详解Linux监控重要进程的实现方法
不管后台服务程序写的多么健壮,还是可能会出现coredump等程序异常退出的情况,但是一般情况下需要在无
人为干预情况下,能够自动重新启动,保证服务进程能够服务用户。这时就需要一个监控程序来实现能够让服务进程自动重新启动。查阅相关资料及尝试一些方法之后,总结linux系统监控重要进程的实现方法:脚本检测和子进程替换。
1、脚本检测
(1)基本思路:通过shell命令(ps-e|grep"$1"|grep-v"grep"|wc-l)获取$1($1代表进程的名字)的进程数,脚本根据进程数来决定下一步的操作。通过一个死循环,每隔几秒检查一次系统中的指定程序的进程数,这里也可使用crontab来实现。
(2)具体实现过程的代码如下:[supervisor.sh]
#!/bin/sh #supervisorprocess LOG_FILE=/var/log/supervisor_sh.log #logfunction functionlog(){ localt=$(date+"%F%X") echo"[$t]$0:$1">>${LOG_FILE} } #checkprocessnumber #$1:processname functioncheck_process(){ if[-z$1];then log"Inputparameterisempty." return0 fi p_num=$(ps-e|grep"$1"|grep-v"grep"|wc-l) log"p_num=$p_num" echo$p_num } #supervisorprocess while[1] do declare-ich_num p_name="apache2" ch_num=$(check_process$p_name) if[$ch_num-eq0];then killall$p_name service$p_namestart fi sleep3 done
2、子进程替换
(1)基本思路:
a.使用fork函数创建一个新的进程,在进程表中创建一个新的表项,而创建者(即父进程)按原来的流程继续执行,子进程执行自己的控制流程
b.运用execv函数把当前进程替换为一个新的进程,新进程由path或file参数指定,可以使用execv函数将程序的执行从一个程序切换到另一个程序
c.当fork启动一个子进程时,子进程就有了它自己的生命周期并将独立运行,此时可以在父进程中调用wait函数让父进程等待子进程的结束
(2)基本的实现步骤:
a.首先使用fork系统调用,创建子进程
b.在子进程中使用execv函数,执行需要自动重启的程序
c.在父进程中执行wait函数等待子进程的结束,然后重新创建一个新的子进程
(3)具体实现的代码如下:supervisor.c
/** * *supervisor * *date:2016-08-10 * */ #include#include #include #include #include #include #include #include #defineLOG_FILE"/var/log/supervisor.log" voids_log(char*text){ time_tt; structtm*tm; char*log_file; FILE*fp_log; chardate[128]; log_file=LOG_FILE; fp_log=fopen(log_file,"a+"); if(NULL==fp_log){ fprintf(stderr,"Couldnotopenlogfile'%s'forwriting\n",log_file); } time(&t); tm=localtime(&t); strftime(date,127,"%Y-%m-%d%H:%M:%S",tm); /*writethemessagetostdoutand/orlogfile*/ fprintf(fp_log,"[%s]%s\n",date,text); fflush(fp_log); fclose(fp_log); } intmain(intargc,char**argv){ intret,i,status; char*child_argv[100]={0}; pid_tpid; if(argc<2){ fprintf(stderr,"Usage:%s ",argv[0]); return-1; } for(i=1;i 0){ pid=wait(&status); fprintf(stdout,"Childprocessid:%d\n",pid); //fprintf(stdout,"waitreturn"); s_log("Waitchildprocessreturn"); } } return0; }
(4)测试验证
a.假设需要自动重启的程序为demo.c,其代码实现如下所示:
/* * *demo * */ #include#include #include #include #include #include #include #include #defineLOG_FILE"/var/log/demo.log" voiddemo_log(intnum){ time_tt; structtm*tm; char*log_file; FILE*fp_log; chardate[128]; log_file=LOG_FILE; fp_log=fopen(log_file,"a+"); if(NULL==fp_log){ fprintf(stderr,"Couldnotopenlogfile'%s'forwriting\n",log_file); } time(&t); tm=localtime(&t); strftime(date,127,"%Y-%m-%d%H:%M:%S",tm); /*writethemessagetostdoutand/orlogfile*/ fprintf(fp_log,"[%s]num=%d\n",date,num); fflush(fp_log); fclose(fp_log); } intmain(intargc,char**argv[]){ intnum=0; while(1){ sleep(10); num++; demo_log(num); } }
b.测试准备和说明:
b1.以上相关服务程序编译后的二进制文件为:supervisor和demo
b2.执行如下测试命令./supervisor./demo
c.测试的结果:
c1.execv(progname,arg)执行成功后,其后的代码不会执行;只有当执行错误时,才会返回-1。原来调用execv进程的代码段会被progname应用程序的代码段替换。
c2.当kill掉子进程时,父进程wait函数会接收到子进程退出的信号,进而循环再启动子进程,此过程实时性非常高。
c3.当kill掉父进程时,子进程会被init进程接管,如果此时再kill掉子进程,则子进程会退出。
c4.当同时kill掉父子进程,则父子进程都会退出。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。