1. 准备一个标准crontab文件 ./crontab
2. crontab -e 将此cron.php脚本加入系统cron
3. cron.php 源码
foreach ( $crontab as $cron ) {
$slices = preg_split("/[s] /", $cron, 6);
if( count($slices) !== 6 ) 继续;
$cmd = array_pop($slices);
$cron_time = implode(' ', $slices);
$next_time = Crontab::parse($cron_time, $now);
if ( $next_time !== $now ) 继续;
$pid = pcntl_fork();
if ($pid == -1) {
die('无法分叉');
} else if ($pid) {
// 我们是父级
pcntl_wait($status, WNOHANG); //防止僵尸儿童
} 其他 {
// 我们是孩子
`$cmd`;
退出;
}
}
/* https://github.com/jkonieczny/PHP-Crontab */
类 Crontab {
/**
* 查找下一个执行时间(标记)解析 crontab 语法,
* 在给定开始时间戳(或当前时间,如果省略)之后
*
* @param string $_cron_string:
*
* 0 1 2 3 4
* * * * * *
* - - - - -
* | | | | |
* | | | | ----- 星期几 (0 - 6)(星期日=0)
* | | | ------- 月 (1 - 12)
* | | --------- 一个月中的某一天 (1 - 31)
* | ----------- 小时 (0 - 23)
* ------------- 分钟 (0 - 59)
* @param int $_after_timestamp 时间戳 [默认=当前时间戳]
* @return int unix timestamp - 下一次执行时间会更长
* 比给定的时间戳(默认为当前时间戳)
* @抛出InvalidArgumentException
*/
公共静态函数parse($_cron_string,$_after_timestamp=null)
{
if(!preg_match('/^((*(/[0-9] )?)|[0-9-,/] )s ((*(/[0-9] )?)|[0-9 -,/] )s ((*(/[0-9] )?)|[0-9-,/] )s ((*(/[0-9] )?)|[0-9-, /] )s ((*(/[0-9] )?)|[0-9-,/] )$/i',trim($_cron_string))){
throw new InvalidArgumentException("无效的 cron 字符串:".$_cron_string);
}
if($_after_timestamp && !is_numeric($_after_timestamp)){
throw new InvalidArgumentException("$_after_timestamp 必须是有效的 unix 时间戳(给定 $_after_timestamp)");
}
$cron = preg_split("/[s] /i",trim($_cron_string));
$start = 空($_after_timestamp)?time():$_after_timestamp;
$date = array( '分钟' =>self::_parseCronNumbers($cron[0],0,59),
'小时' => self::_parseCronNumbers($cron[1],0,23),
'dom' =>self::_parseCronNumbers($cron[2],1,31),
'月' => self::_parseCronNumbers($cron[3],1,12),
'dow' =>self::_parseCronNumbers($cron[4],0,6),
);
// 仅限于 time() 366 - 无需提前检查超过 1 年
for($i=0;$i
if( in_array(intval(date('j',$start $i)),$date['dom']) &&
in_array(intval(date('n',$start $i)),$date['month']) &&
in_array(intval(date('w',$start $i)),$date['dow']) &&
in_array(intval(date('G',$start $i)),$date['hours']) &&
in_array(intval(date('i',$start $i)),$date['分钟'])
){
返回 $start $i;
}
}
返回空;
}
/**
* 获取单个 cron 样式符号并将其解析为数值
*
* @param string $s cron 字符串元素
* @param int $min 最小可能值
* @param int $max 最大可能值
* @return int 解析后的数字
*/
受保护的静态函数 _parseCronNumbers($s,$min,$max)
{
$结果 = array();
$v = 爆炸(',',$s);
foreach($v as $vv){
$vvv = 爆炸('/',$vv);
$step = 空($vvv[1])?1:$vvv[1];
$vvvv = 爆炸('-',$vvv[0]);
$_min = count($vvvv)==2?$vvvv[0]:($vvv[0]=='*'?$min:$vvv[0]);
$_max = count($vvvv)==2?$vvvv[1]:($vvv[0]=='*'?$max:$vvv[0]);
for($i=$_min;$i
$结果[$i]=intval($i);
}
}
ksort($结果);
返回$结果;
}
}