守护多进程

代码网上找了些、原本只是守护进程、现在是单任务多进程守护、

因为守护进程一般都是后台死循环、所以执行不到下一个任务

代码只能在linux下运行、且依赖 pcntl扩展

启动

[root@localhost wwwroot]# php ./MutiProcesserDeamon.php start

Start , Fork num : 5

查看:

[root@localhost ~]# ps -ef | grep muti_processer | grep -v grep
root      3720     1  0 14:32 ?           00:00:00 muti_processer_worker              
root      3721  3720  0 14:32 ?        00:00:00 muti_processer_worker              
root      3722  3720  0 14:32 ?        00:00:00 muti_processer_worker              
root      3723  3720  0 14:32 ?        00:00:00 muti_processer_worker              
root      3724  3720  0 14:32 ?        00:00:00 muti_processer_worker              

root      3725  3720  0 14:32 ?        00:00:00 muti_processer_worker 


[root@localhost wwwroot]# php ./MutiProcesserDeamon.php status
Is Running , Exists process num 5

杀掉:

[root@localhost wwwroot]# php ./MutiProcesserDeamon.php stop
Kill process 3710
Kill process 3711
Kill process 3712
Kill process 3713
Kill process 3714
Kill process 3715

Stoped

代码:

<?php

class MutiProcesserDeamon {
    public $pidFile;
    public  $processNamePrfix ='task_processer';
    private $_jobs = null;
    public  $pidpath= '/tmp';
    public  $forkNum = 5;
 
    public function __construct($pidFile='') {
        if(!$pidFile){
            $this->pidFile = $this->pidpath . '/' .__CLASS__ .'_'.date('Ymd'). '_pid.log';
        }else{
            $this->pidFile = $pidFile;
        }
    }
 
    private function _demonize() {
        if (php_sapi_name() != 'cli') {
            die('只可在命令行执行 php ./MutiProcesserDeamon.php start|stop|status');
        }
        //洗掉原本存在的进程号
        try{ if(file_exists($this->pidFile))unlink($this->pidFile);}catch(Exception $e){}
        umask(0);
        $pid = pcntl_fork();
        if (-1 === $pid) {
            die('fork fail');
        } elseif ($pid > 0) {
            //并没有真正的死掉、保存下来,stop的时候一起杀掉
            file_put_contents($this->pidFile, $pid.PHP_EOL,FILE_APPEND);
            // pcntl_wait($status); //就不会退出、卡在命令行
            exit;
        }
        posix_setsid();
        $child = 0;//当前的子进程数量
        while (true) {
            $child++;
            $pid = pcntl_fork();
            cli_set_process_title($this->processNamePrfix."_worker");
            if ($pid) {
                file_put_contents($this->pidFile, $pid.PHP_EOL,FILE_APPEND);
                if ($child >= $this->forkNum) {
                    pcntl_wait($status);
                    $child--;
                }
            } else {
                $_pid = getmypid();
                if (!empty($this->_jobs)) {
                    $job = $this->_jobs;
                    if (!empty($job['argv'])) {
                        call_user_func($job['function'], $job['argv'],$_pid);
                    } else {
                        call_user_func($job['function'],$_pid);
                    }
                }
                exit(0);
            }
        }            
        return;
    }
 
 
    private function _getPid() {
        if (!file_exists($this->pidFile)) {
            return false;
        }
        return file($this->pidFile);
    }
  
    public function start($procNums=5) {
        $pids = $this->_getPid();
        if ($pids) {
            echo 'Running , Exists process num '.(count($pids)-1).PHP_EOL;
        } else {
            echo 'Start , Fork num : '.$this->forkNum.PHP_EOL;
            $this->_demonize($procNums);
        }
    }
 
    public function stop() {
        $pids = $this->_getPid();
        if ($pids) {
            foreach($pids as $pid){
                $pid = (int)trim($pid);
                posix_kill($pid, SIGTERM);
                echo 'Kill process ' . $pid.PHP_EOL; 
            }
            unlink($this->pidFile);
            echo 'Stoped' . PHP_EOL;
        } else {
			//防止文件内进程号不准、没杀死
            $cmd = "ps aux | grep ".$this->processNamePrfix."| grep -v grep |awk '{print $2}' | xargs kill -9";
            exec($cmd);
            echo "Not Running" . PHP_EOL;
        }
    }
 
    public function status() {
        $pids = $this->_getPid();
        if ($pids) {
            echo 'Is Running , Exists process num '.(count($pids)-1).PHP_EOL;
        } else {
            echo 'Not Running' . PHP_EOL;
        }
    } 
    public function setJob($jobs = array()) {
        if (!isset($jobs['function']) || empty($jobs['function'])) {
            echo "Need function param\n";
        }
 
        if (!isset($jobs['argv']) || empty($jobs['argv'])) {
            $jobs['argv'] = "";
        }
		 //因为守护是死循环程序、所以一次只能加一个任务
        $this->_jobs = $jobs;
    }
 
    public function run($argv) {
        $param = is_array($argv) && count($argv) == 2 ? $argv[1] : null;
        switch ($param) {
            case 'start':
                $this->start();
                break;
            case 'stop':
                $this->stop();
                break;
            case 'status':
                $this->status();
                break;
            default:
                echo "params: start|stop|status " . PHP_EOL;
                break;
        }
    }
}
 
$service = new MutiProcesserDeamon();
$service->forkNum = 5;
$service->pidpath = '/tmp';
$service->processNamePrfix = 'fuckqq';
$service->setJob(array(
    'function' => 'test',
    'argv' => 'param'
));
$service->run($argv);

//这种尤其适合后台接受、或者是读取队列,比如redis出列 
function test($param,$pid) {
    $i = 0;
    while (true) {
        $tm = date('Y-m-d H:i:s');
        file_put_contents('/home/wwwroot/d.log', "{$i} {$pid} Now is {$tm} ". PHP_EOL,FILE_APPEND);
        $i++;
        sleep(5);
    }
}

猜你喜欢

转载自blog.csdn.net/swg0110/article/details/80828847