request->isCli()) { $this->error('Autotask script only work at client!'); } parent::_initialize(); // 清除错误 error_reporting(0); // 设置永不超时 set_time_limit(0); } /** * 执行定时任务 */ public function index() { $withPcntl = false; $pool = null; $config = get_addon_config('crontab'); $mode = $config['mode'] ?? 'pcntl'; if ($mode == 'pcntl' && function_exists('pcntl_fork')) { $withPcntl = true; $pool = new \Jenner\SimpleFork\Pool(); } $time = time(); $logDir = LOG_PATH . 'crontab' . DS; if (!is_dir($logDir)) { mkdir($logDir, 0755); } //筛选未过期且未完成的任务 $crontabList = Crontab::where('status', '=', 'normal')->order('weigh DESC,id DESC')->select(); $execTime = time(); foreach ($crontabList as $crontab) { $update = []; $execute = false; if ($time < $crontab['begintime']) { //任务未开始 continue; } if ($crontab['maximums'] && $crontab['executes'] > $crontab['maximums']) { //任务已超过最大执行次数 $update['status'] = 'completed'; } else { if ($crontab['endtime'] > 0 && $time > $crontab['endtime']) { //任务已过期 $update['status'] = 'expired'; } else { //重复执行 //如果未到执行时间则继续循环 $cron = CronExpression::factory($crontab['schedule']); if (!$cron->isDue() || ($execTime && date("YmdHi", $execTime) === date("YmdHi", $crontab['executetime']))) { continue; } $execute = true; } } // 如果允许执行 if ($execute) { $update['executetime'] = $time; $update['executes'] = $crontab['executes'] + 1; $update['status'] = ($crontab['maximums'] > 0 && $update['executes'] >= $crontab['maximums']) ? 'completed' : 'normal'; } // 如果需要更新状态 if (!$update) { continue; } // 更新状态 $crontab->save($update); Db::connect()->close(); // 将执行放在后面是为了避免超时导致多次执行 if (!$execute) { continue; } $runnable = new \addons\crontab\library\CommandRunnable($crontab); if ($withPcntl) { $process = new \Jenner\SimpleFork\Process($runnable); $name = $crontab['title']; $pool->execute($process); } else { $runnable->run(); } } if ($withPcntl && $pool) { $pool->wait(); } return "Execute completed!\n"; } }