使用 php 实现类似 linux crontab 的定时任务功能,支持秒级定时任务类
/** * Class Crontab * description: 使用 php 实现类似 linux crontab 的定时任务功能,支持秒级定时 * author: http://www.maopiaopiao.com/ */ class Crontab { /** * 判断某个时间点是否在 cron 规则之内 * @param $cron * @param $time * @return bool */ public static function parseCron($cron, $time) { $cronArray = self::getCronArray($cron); $now = explode(' ', date('s i G j n w', $time)); foreach ($now as $key => $piece) { if (!in_array($piece, $cronArray[$key])) { return false; } } return true; } /** * @param $cron * @return array */ public static function getCronArray($cron) { $cronArray = explode(' ', $cron); $timeArray = []; $dimensions = [ [0, 59], //seconds [0, 59], //Minutes [0, 23], //Hours [1, 31], //Days [1, 12], //Months [0, 6] //Weekdays ]; foreach ($cronArray as $key => $item) { list($repeat, $every) = explode('/', $item, 2) + [false, 1]; if ($repeat === '*') { $timeArray[$key] = range($dimensions[$key][0], $dimensions[$key][1]); } else { // 处理逗号拼接的命令 $tmpRaw = explode(',', $item); foreach ($tmpRaw as $tmp) { // 处理10-20这样范围的命令 $tmp = explode('-', $tmp, 2); if (count($tmp) == 2) { $timeArray[$key] = array_merge($timeArray[$key], range($tmp[0], $tmp[1])); } else { $timeArray[$key][] = $tmp[0]; } } } // 判断*/10 这种类型的 if ($every > 1) { foreach ($timeArray[$key] as $k => $v) { if ($v % $every != 0) { unset($timeArray[$key][$k]); } } } } return $timeArray; } }
使用示例:
<?php include 'Crontab.php'; $cron_list = [ //['cron' => '秒 分 时 日 月 周', 'echo' => '任务名称'], ['cron' => '0 */1 * * * *', 'echo' => '第一个任务执行了'], ['cron' => '0 */2 * * * *', 'echo' => 'www.maopiaopiao.com'], ['cron' => '20 */3 * * * *', 'echo' => '第三个任务执行了'], ['cron' => '5 */5 * * * *', 'echo' => '第四个任务执行了'], ['cron' => '0 41 16 29 * *', 'echo' => '第5个任务执行了'] ]; echo date('Y-m-d H:i:s', time()) . "\r\n"; while (true) { $time = time(); foreach ($cron_list as &$cron) { $result = Crontab::parseCron($cron['cron'], $time); if ($result) { echo date('Y-m-d H:i:s', $time) . ' ' . $cron['cron'] . ' ' . $cron['echo'] . "\r\n"; } } //echo date('Y-m-d H:i:s', $time) . "\r\n"; sleep(1); }
输出结果如下: