Home > php教程 > php手册 > 用php写的进程守护,进程管理,进程出错自动启动功能,适合服务器管理员使用

用php写的进程守护,进程管理,进程出错自动启动功能,适合服务器管理员使用

WBOY
Release: 2016-06-13 10:56:39
Original
1266 people have browsed it

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

运行示例:

 php supervisor.php /usr/local/nginx/bin/nginx nobody  (这后面还可以加上对应命令的参数,无参数留空就行) &


参数介绍:第一个为命令行的php可执行程序,第二个为本文下面的代码文件,第三个是需要启动的可以执行的程序路径,第四个是用什么角色启动它,后面的是预留参数,全部传递给这个可执行程序。

 

 

 

优点:

1、 需要守护的程序在 非daemon 状态下运行,出现错误退出时能立即重启

2、程序为daemon运行时,定时检测运行状态,1秒内重启

3、能够在特定的时间内设置重启的次数,次数超过配置数就不再重启,防止应用程序出现特别情况无法重启。

 


建议:

建议把程序调成非daemon状态下运行。

 


把以下代码复制另存为supervisor.php文件即可


[php]
//author email: tipboy@qq.com  
$_retry_times=5; 
$_retry_times_duration=60;//这个是多少时间内,重启了多少次,就不需要再重启了  
$_times_arr=array(); 
$args=$_SERVER['argv']; 
if(count($args) { 
    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         { 
            //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; 
    } 

?> 

//author email: tipboy@qq.com
$_retry_times=5;
$_retry_times_duration=60;//这个是多少时间内,重启了多少次,就不需要再重启了
$_times_arr=array();
$args=$_SERVER['argv'];
if(count($args) {
 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   {
   //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;
 }
}
?>


 

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Recommendations
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template