程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> 用php寫的進程守護,進程管理,進程出錯自動啟動功能,適合服務器管理員使用

用php寫的進程守護,進程管理,進程出錯自動啟動功能,適合服務器管理員使用

編輯:關於PHP編程

只要安裝了php 命令行工具就行

運行示例:

 php supervisor.php /usr/local/nginx/bin/nginx nobody  (這後面還可以加上對應命令的參數,無參數留空就行) &


參數介紹:第一個為命令行的php可執行程序,第二個為本文下面的代碼文件,第三個是需要啟動的可以執行的程序路徑,第四個是用什麼角色啟動它,後面的是預留參數,全部傳遞給這個可執行程序。

 

 

 

優點:

1、 需要守護的程序在 非daemon 狀態下運行,出現錯誤退出時能立即重啟

2、程序為daemon運行時,定時檢測運行狀態,1秒內重啟

3、能夠在特定的時間內設置重啟的次數,次數超過配置數就不再重啟,防止應用程序出現特別情況無法重啟。

 


建議:

建議把程序調成非daemon狀態下運行。

 


把以下代碼復制另存為supervisor.php文件即可


[php]
<?php 
//author email: [email protected]  
$_retry_times=5; 
$_retry_times_duration=60;//這個是多少時間內,重啟了多少次,就不需要再重啟了  
$_times_arr=array(); 
$args=$_SERVER['argv']; 
if(count($args)<3) 

    write_log("args num error!"); 
    write_log("etc: php supervisor.php /usr/local/nginx/bin/nginx nobody  xxx"); 
    write_log("第一個參數就是本文件,第二個參數是要監控的可執行文件路徑,第三個是使用哪個用戶執行,接下來的參數就是執行該執行文件所用的參數"); 
    exit(); 

//$args[0] 為本文件名  
$path=$args[1]; 
$username=$args[2]; 
for($i=3;$i>0;$i--) 
    array_shift($args); 
 
while(1){ 
    $pid=pcntl_fork(); 
    if($pid==0) 
    { 
        //write_log("child ".getmypid()." run");  
        pcntl_exec($path,$args,$_SERVER); 
        write_log("execute file failed");  
        exit(0); 
    } 
    else if($pid>0) 
    { 
        //write_log(" main  pid:".getmypid().", child_pid:".$pid);   
        $endpid=pcntl_waitpid($pid,$status,2);           
        //write_log("status:".$status);       
        if($status==0) 
        { 
            //說明可能是daemon程序,後台運行  
            if(file_exists("/proc/".($pid+1)."/stat")) 
            { 
                //說明進程存在,需要定時判斷  
                write_log("program start success");  
                 
                for (;;)  
                {  
                    if(file_exists("/proc/".($pid+1)."/stat")) 
                    { 
                        //write_log("program is alive");   
                        usleep(1000000); 
                    } 
                    else 
                    { 
                        write_log("program die");  
                        break; 
                    } 
                } 
                     
            } 
            else 
            { 
                //說明進程不存在,並且不是非daemon狀態。  
                write_log("program start failed");  
                exit(0); 
            } 
        } 
        else if($status>0) 
        { 
            //說明是非daemon 程序,退出來了,需要重新啟動  
            write_log("program die");  
            //continue;  
        } 
        else 
        { 
            exit(0); 
        } 
 
        if(chk_need_start($_times_arr,$_retry_times_duration,$_retry_times)) 
        { 
            continue; 
        } 
        else 
        { 
            break; 
        } 
    } 
}; 
 
 
function write_log($msg) 

    print(date('Y-m-d H:i:s').' '.$msg."\n"); 

 
function chk_need_start(&$_times_arr,$_retry_times_duration,$_retry_times) 
{    
    foreach($_times_arr as $k=>$v) 
    { 
        //write_log("duration:".$_retry_times_duration);  
        if($k<time()-$_retry_times_duration) 
        { 
            //write_log("do unset");  
            unset($_times_arr[$k]); 
        }    
    } 
    //write_log("buffer count:".count($_times_arr));  
    if(count($_times_arr)>=$_retry_times) 
    { 
 
        return false; 
    } 
    else 
    { 
        $_times_arr[time()]=1; 
         
        return true; 
    } 

?> 

<?php
//author email: [email protected]
$_retry_times=5;
$_retry_times_duration=60;//這個是多少時間內,重啟了多少次,就不需要再重啟了
$_times_arr=array();
$args=$_SERVER['argv'];
if(count($args)<3)
{
 write_log("args num error!");
 write_log("etc: php supervisor.php /usr/local/nginx/bin/nginx nobody  xxx");
 write_log("第一個參數就是本文件,第二個參數是要監控的可執行文件路徑,第三個是使用哪個用戶執行,接下來的參數就是執行該執行文件所用的參數");
 exit();
}
//$args[0] 為本文件名
$path=$args[1];
$username=$args[2];
for($i=3;$i>0;$i--)
 array_shift($args);

while(1){
 $pid=pcntl_fork();
 if($pid==0)
 {
  //write_log("child ".getmypid()." run");
  pcntl_exec($path,$args,$_SERVER);
  write_log("execute file failed");
  exit(0);
 }
 else if($pid>0)
 {
  //write_log(" main  pid:".getmypid().", child_pid:".$pid);
  $endpid=pcntl_waitpid($pid,$status,2);   
  //write_log("status:".$status);  
  if($status==0)
  {
   //說明可能是daemon程序,後台運行
   if(file_exists("/proc/".($pid+1)."/stat"))
   {
    //說明進程存在,需要定時判斷
    write_log("program start success");
    
    for (;;)
    {
     if(file_exists("/proc/".($pid+1)."/stat"))
     {
      //write_log("program is alive");
      usleep(1000000);
     }
     else
     {
      write_log("program die");
      break;
     }
    }
     
   }
   else
   {
    //說明進程不存在,並且不是非daemon狀態。
    write_log("program start failed");
    exit(0);
   }
  }
  else if($status>0)
  {
   //說明是非daemon 程序,退出來了,需要重新啟動
   write_log("program die");
   //continue;
  }
  else
  {
   exit(0);
  }

  if(chk_need_start($_times_arr,$_retry_times_duration,$_retry_times))
  {
   continue;
  }
  else
  {
   break;
  }
 }
};


function write_log($msg)
{
 print(date('Y-m-d H:i:s').' '.$msg."\n");
}

function chk_need_start(&$_times_arr,$_retry_times_duration,$_retry_times)

 foreach($_times_arr as $k=>$v)
 {
  //write_log("duration:".$_retry_times_duration);
  if($k<time()-$_retry_times_duration)
  {
   //write_log("do unset");
   unset($_times_arr[$k]);
  } 
 }
 //write_log("buffer count:".count($_times_arr));
 if(count($_times_arr)>=$_retry_times)
 {

  return false;
 }
 else
 {
  $_times_arr[time()]=1;
  
  return true;
 }
}
?>


 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved