123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- <?php
- namespace app\index\controller;
- use app\common\model\Crontab;
- use fast\Date;
- use fast\Http;
- use think\Controller;
- use think\Db;
- use think\Exception;
- use think\Log;
- /**
- * 定时任务接口
- *
- * 以Crontab方式每分钟定时执行,且只可以Cli方式运行
- * @internal
- */
- class Autotask extends Controller
- {
- /**
- * 初始化方法,最前且始终执行
- */
- public function _initialize()
- {
- // 只可以以cli方式执行
- if (!$this->request->isCli())
- $this->error('Autotask script only work at client!');
- parent::_initialize();
- // 清除错误
- error_reporting(0);
- // 设置永不超时
- set_time_limit(0);
- }
- /**
- * 执行定时任务
- */
- public function crontab()
- {
- $time = time();
- $logDir = LOG_PATH . 'crontab/';
- if (!is_dir($logDir))
- {
- mkdir($logDir);
- }
- //筛选未过期且未完成的任务
- $crontabList = Crontab::where('status', '=', 'normal')->order('weigh desc,id desc')->select();
- foreach ($crontabList as $crontab)
- {
- $update = [];
- $execute = FALSE;
- if ($time < $crontab['begintime'])
- {
- //任务未开始
- continue;
- }
- if ($crontab['maximums'] && $crontab['executes'] > $crontab['maximums'])
- {
- //任务已超过最大执行次数
- $update['status'] = 'finished';
- }
- else if ($crontab['endtime'] > 0 && $time > $crontab['endtime'])
- {
- //任务已过期
- $update['status'] = 'expired';
- }
- else
- {
- //重复执行
- //如果未到执行时间则继续循环
- if (!Date::cron($crontab['schedule']))
- continue;
- $execute = TRUE;
- }
- // 如果允许执行
- if ($execute)
- {
- $update['executetime'] = $time;
- $update['executes'] = $crontab['executes'] + 1;
- $update['status'] = ($crontab['maximums'] > 0 && $update['executes'] >= $crontab['maximums']) ? 'finished' : 'normal';
- }
- // 如果需要更新状态
- if (!$update)
- continue;
- // 更新状态
- $crontab->save($update);
- // 将执行放在后面是为了避免超时导致多次执行
- if (!$execute)
- continue;
- try
- {
- if ($crontab['type'] == 'url')
- {
- if (substr($crontab['content'], 0, 1) == "/")
- {
- // 本地项目URL
- exec('nohup php ' . ROOT_PATH . 'public/index.php ' . $crontab['content'] . ' >> ' . $logDir . date("Y-m-d") . '.log 2>&1 &');
- }
- else
- {
- // 远程异步调用URL
- Http::sendAsyncRequest($crontab['content']);
- }
- }
- else if ($crontab['type'] == 'sql')
- {
- // 执行SQL
- Db::getPdo()->exec($crontab['content']);
- }
- else if ($crontab['type'] == 'shell')
- {
- // 执行Shell
- exec('nohup php ' . $crontab['content'] . ' >> ' . $logDir . date("Y-m-d") . '.log 2>&1 &');
- }
- }
- catch (Exception $e)
- {
- Log::record($e->getMessage());
- }
- }
- return 'Execute completed!';
- }
- }
|