定时任务管理程序,子进程定期出现僵尸进程,附代码!

自己写的定时任务管理程序,隔10多天就会出现一直执行的子进程(按理说执行最多10分钟,肯定执行完了),导致同一个定时任务不会再次执行,想请教下,代码写的哪里有问题啊?


[work@bank-api01 bmanage.jindanlicai.com]$ ps aux|grep crontab
work     19672 99.9  0.3 374396 30676 ?        R    Feb06 1240:58 省略,执行超过一天了!!
<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Crontab extends CI_Controller
{
    public function daemon()
    {
        if (!is_cli()) {
            exit('请cli下运行');
        }

        $this->crontab_model->reset_crontab_status();//重置任务状态
        while (TRUE) {
            $this->crontab();
        }
    }

    private function crontab()
    {
        $this->benchmark->mark('code_start');

        //每5分钟更新一次任务列表
        if (empty($this->crontab_list) || 0 == date('i') % 1) {
            $this->crontab_list = $this->crontab_model->get_list();
        }

        foreach ($this->crontab_list as $crontab) {
            $c_id = $crontab['c_id'];
            $cron_time = $crontab['time'];
            $command = $crontab['command'];

            try {
                $cron_start_time = $this->cronlib->parse($cron_time);//https://github.com/jkonieczny/PHP-Crontab/blob/master/Crontab.class.php
            } catch (Exception $e) {
                $this->_write_log('error,cron_time格式错误');
                continue;
            }

            $current_minute_time = strtotime(date('YmdHi00'));
            $next_minute_time = $current_minute_time + 60;
            if ($cron_start_time >= $current_minute_time && $cron_start_time < $next_minute_time) {
                $row = $this->crontab_model->get_by_cid($c_id);
                if (strtotime($row['last_start_time']) >= $current_minute_time && strtotime($row['last_start_time']) < $next_minute_time) {
                    //$this->_write_log("id:{$c_id},command:{$command},当前分钟已经运行过一次了");
                    continue;
                }
                if ($row['status'] == Crontab_model::STATUS_DOING) {
                    $this->_write_log("id:{$c_id},command:{$command},运行中");
                    continue;
                }

                $this->_write_log("id:{$c_id},command:{$command},开始运行");
                $this->_children_process($command, $c_id);
                continue;
            }
        }

        $this->benchmark->mark('code_end');
        $exec_time = $this->benchmark->elapsed_time('code_start', 'code_end');
        if ($exec_time >= 59) {
            $this->_write_log("error,单次循环运行时间>59秒!");//测试100个任务,都是微妙级别
        }

        foreach ($this->children_process as $key => $pid) {
            $res = pcntl_waitpid($pid, $status, WNOHANG);
            if ($res == -1 || $res > 0) {
                $this->_write_log("子进程:{$pid},捕获退出");
                unset($this->children_process[$key]);
            }
        }

        sleep(59 - $exec_time);
    }

    private function _children_process($command, $c_id)
    {
        $pid = pcntl_fork();
        if ($pid == -1) {
            $this->_write_log('error,can not fork');
            die;
        }
        if ($pid) {
            $this->children_process[] = $pid;
        } else {
            ini_set('max_execution_time', 1800);//最大执行时间30分钟

            $children_pid = posix_getpid();
            $this->_write_log("子进程:{$children_pid},运行");

            //before执行
            $start_time = date('Y-m-d H:i:s');
            $this->crontab_model->update_by_cid($c_id, [
                'status' => Crontab_model::STATUS_DOING,
                'last_start_time' => $start_time,
            ]);

            //执行
            $stdout = shell_exec($command);

            $this->_write_log("子进程:{$children_pid},运行结束");
            die;
        }
    }
}

strace -p 出现

Process 19671 attached - interrupt to quit
fcntl(13, F_SETFL, O_RDWR|O_NONBLOCK) = 0
fcntl(13, F_GETFL) = 0x802 (flags O_RDWR|O_NONBLOCK)
fcntl(13, F_SETFL, O_RDWR) = 0
fcntl(13, F_GETFL) = 0x2 (flags O_RDWR)
fcntl(13, F_SETFL, O_RDWR|O_NONBLOCK) = 0

wait4(-1,

这类信息

阅读 4.3k
1 个回答

因为只有一个crontab程序总出现卡死,猜测是他的问题,把他增加了详细日志,观察下

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题