Autotask.php
4.0 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<?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'] = 'completed';
}
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']) ? 'completed' : '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')
{
//这里需要强制重连数据库,使用已有的连接会报2014错误
$connect = Db::connect([], true);
$connect->execute("select 1");
// 执行SQL
$connect->getPdo()->exec($crontab['content']);
}
else if ($crontab['type'] == 'shell')
{
// 执行Shell
exec($crontab['content'] . ' >> ' . $logDir . date("Y-m-d") . '.log 2>&1 &');
}
}
catch (Exception $e)
{
Log::record($e->getMessage());
}
}
return 'Execute completed!';
}
}