1、使用腳本實現自動重啓
首先想到的最簡單的使用shell腳本,大概思路:
ps -ef | grep “$1″ | grep -v “grep” | wc –l 是獲取 $1 ($1 代表進程的名字)的進程數,腳本根據進程數來決定下一步的操作。通過一個死循環,每隔 1 秒檢查一次系統中的指定程序的進程數,這裏也可使用crontab來實現。
這種方法比較土,還是可以基本解決問題,但是有1s的延遲,筆者在應用中未採用這種方法,有關這個shell腳本,請參看文章後面的附件代碼。
2、exec+fork方式
筆者最終採用的exec+fork方式來實現的,具體思想如下:
1,exec函數把當前進程替換爲一個新的進程,新進程由path或file參數指定。可以使用exec函數將程序的執行從一個程序切換到另一個程序;
2,fork函數是創建一個新的進程,在進程表中創建一個新的表項,而創建者(即父進程)按原來的流程繼續執行,子進程執行自己的控制流程;
3,wait 當fork啓動一個子進程時,子進程就有了它自己的生命週期並將獨立運行,我們可以在父進程中調用wait函數讓父進程等待子進程的結束;
相信介紹到這裏,讀者已經能夠想到解決方法了:1)首先使用fork系統調用,創建子進程,2)在子進程中使用exec函數,執行需要自動重啓的程序,3) 在父進程中執行wait等待子進程的結束,然後重新創建一個新的子進程。
使用方法:
#./portmap 需要監控的程序的路徑
#args portmap 需要的參數
$ ./supervisor ./portmap args.....
代碼如下:
/** supervisor
* author: liyangguang ([email protected])
* date: 2011-01-21 21:04:01
* changes * 1, execl to execv
*/
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
int main(int argc,char **argv){
int ret, i, status;
char*child_argv[100]= {0};
pid_t pid;
if(argc < 2){
fprintf(stderr,"Usage:%s \n", argv[0]);
return-1;
}
for(i = 1; i< argc;++i){
child_argv[i-1]= (char *)malloc(strlen(argv[i])+1);
strncpy(child_argv[i-1], argv[i], strlen(argv[i]));
child_argv[i-1][strlen(argv[i])]= '\0';
}
while(1){
pid = fork();
if(pid == -1){
fprintf(stderr,"fork() error.errno:%d error:%s\n", errno, strerror(errno));
break;
}
if(pid == 0){
ret = execv(child_argv[0],(char**)child_argv);
//ret = execl(child_argv[0], "portmap", NULL, 0);
if(ret < 0){
fprintf(stderr,"execv ret:%d errno:%d error:%s\n", ret, errno, strerror(errno));
continue;
}
exit(0);
}
if(pid > 0){
pid = wait(&status); fprintf(stdout,"wait return");
}
}
return0;
}
shell腳本方式的代碼如下:
# 函數: CheckProcess
# 功能: 檢查一個進程是否存在
# 參數: $1 --- 要檢查的進程名稱
# 返回: 如果存在返回0, 否則返回1.
#------------------------------------------------------------------------------
CheckProcess()
{
# 檢查輸入的參數是否有效
if [ "$1" = "" ];
then
return 1
fi
#$PROCESS_NUM獲取指定進程名的數目,爲1返回0,表示正常,不爲1返回1,表示有錯誤,需要重新啓動
PROCESS_NUM=`ps -ef | grep "$1" | grep -v "grep" | wc -l`
if [ $PROCESS_NUM -eq 1 ];
then
return 0
else
return 1
fi
}
# 檢查test實例是否已經存在
while [ 1 ] ; do
CheckProcess "test"
CheckQQ_RET=$?
if [ $CheckQQ_RET -eq 1 ];
then
# 殺死所有test進程,可換任意你需要執行的操作
killall -9 test
exec ./test &
fi
sleep 1
done
轉自:http://yaronspace.cn/blog/archives/1095