国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 服務器 > Web服務器 > 正文

詳解Linux監控重要進程的實現方法

2024-09-01 13:54:40
字體:
來源:轉載
供稿:網友

不管后臺服務程序寫的多么健壯,還是可能會出現core dump等程序異常退出的情況,但是一般情況下需要在無

人為干預情況下,能夠自動重新啟動,保證服務進程能夠服務用戶。這時就需要一個監控程序來實現能夠讓服務進程自動重新啟動。查閱相關資料及嘗試一些方法之后,總結linux系統監控重要進程的實現方法:腳本檢測和子進程替換。

1、腳本檢測

(1) 基本思路: 通過shell命令(ps -e | grep "$1" | grep -v "grep" | wc -l) 獲取 $1 ($1 代表進程的名字)的進程數,腳本根據進程數來決定下一步的操作。通過一個死循環,每隔幾秒檢查一次系統中的指定程序的進程數,這里也可使用crontab來實現。

(2) 具體實現過程的代碼如下: [ supervisor.sh ]

#! /bin/sh # supervisor process   LOG_FILE=/var/log/supervisor_sh.log  # log function  function log() {   local t=$(date +"%F %X")   echo "[ $t ] $0 : $1 " >> ${LOG_FILE} }  # check process number  # $1 : process name  function check_process() {   if [ -z $1 ]; then     log "Input parameter is empty."     return 0      fi      p_num=$(ps -e | grep "$1" | grep -v "grep" | wc -l)   log "p_num = $p_num"    echo $p_num }  # supervisor process  while [ 1 ] do    declare -i ch_num   p_name="apache2"   ch_num=$(check_process $p_name)   if [ $ch_num -eq 0 ]; then     killall $p_name     service $p_name start    fi   sleep 3  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 <stdio.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/wait.h> #include <stdlib.h> #include <time.h>  #define LOG_FILE "/var/log/supervisor.log"  void s_log(char *text) {   time_t   t;   struct tm *tm;   char *log_file;   FILE *fp_log;   char date[128];      log_file = LOG_FILE;   fp_log = fopen(log_file, "a+");   if (NULL == fp_log) {     fprintf(stderr, "Could not open logfile '%s' for writing/n", log_file);   }      time(&t);   tm = localtime(&t);   strftime(date, 127, "%Y-%m-%d %H:%M:%S", tm);      /* write the message to stdout and/or logfile */     fprintf(fp_log, "[%s] %s/n", date, text);   fflush(fp_log);   fclose(fp_log); }   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 <exe_path> <args...>", 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", errno, strerror(errno));       break;     }     if (pid == 0) {       s_log(child_argv[0]);       ret = execv(child_argv[0], (char **)child_argv);       s_log("execv return");       if (ret < 0) {         fprintf(stderr, "execv ret:%d errno:%d error:%s", ret, errno, strerror(errno));         continue;       }       s_log("exit child process");       exit(0);     }     if (pid > 0) {       pid = wait(&status);       fprintf(stdout, "Child process id: %d/n", pid);       //fprintf(stdout, "wait return");       s_log("Wait child process return");     }   }      return 0; } 

(4) 測試驗證

a. 假設需要自動重啟的程序為demo.c,其代碼實現如下所示:

/* * * demo  * */ #include <stdio.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/wait.h> #include <stdlib.h> #include <time.h>  #define LOG_FILE "/var/log/demo.log"  void demo_log(int num) {   time_t   t;   struct tm *tm;   char *log_file;   FILE *fp_log;   char date[128];      log_file = LOG_FILE;   fp_log = fopen(log_file, "a+");   if (NULL == fp_log) {     fprintf(stderr, "Could not open logfile '%s' for writing/n", log_file);   }      time(&t);   tm = localtime(&t);   strftime(date,127,"%Y-%m-%d %H:%M:%S",tm);      /* write the message to stdout and/or logfile */     fprintf(fp_log, "[%s] num = %d/n", date, num);   fflush(fp_log);   fclose(fp_log); }   int main(int argc, char **argv[]) {   int num = 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掉父子進程,則父子進程都會退出。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到服務器教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 建昌县| 麟游县| 集安市| 五大连池市| 清河县| 惠水县| 夏邑县| 交口县| 来凤县| 阿合奇县| 岚皋县| 南投县| 定襄县| 房产| 军事| 滦南县| 秦皇岛市| 新源县| 文昌市| 财经| 葫芦岛市| 溆浦县| 台江县| 大冶市| 张掖市| 牡丹江市| 马尔康县| 苗栗县| 怀柔区| 日喀则市| 丹凤县| 景泰县| 沙河市| 阳东县| 大洼县| 潼南县| 榆中县| 普陀区| 江都市| 兴城市| 贵南县|