|
discuz_cron.php
<?php
/**
* [Discuz!] (C)2001-2099 Comsenz Inc.
* This is NOT a freeware, use is subject to license terms
*
* $Id: discuz_cron.php 25833 2011-11-24 01:12:09Z monkey $
*/
if(!defined('IN_DISCUZ')) {
exit('Access Denied');
}
class discuz_cron
{
public static function run($cronid = 0) {
global $_G;
//取出这个时间点或这个时间点之前的计划任务
$cron = $cronid ? C::t('common_cron')->fetch($cronid) : C::t('common_cron')->fetch_nextrun(TIMESTAMP);
//进程名称
$processname ='DZ_CRON_'.(empty($cron) ? 'CHECKER' : $cron['cronid']);
if($cronid && !empty($cron)) {
//此计划任务有效,解锁
discuz_process::unlock($processname);
}
if(discuz_process::islocked($processname, 600)) {
//没有加锁,加锁,返回false,若已加锁,返回true,终止程序进行
return false;
}
if($cron) {
$cron['filename'] = str_replace(array('..', '/', '\\'), '', $cron['filename']);
$cronfile = DISCUZ_ROOT.'./source/include/cron/'.$cron['filename'];
$cron['minute'] = explode("\t", $cron['minute']);
self::setnextime($cron); //更新此计划任务的上次执行时间和下次执行时间
@set_time_limit(1000); //设置允许脚本运行的时间,单位为秒
@ignore_user_abort(TRUE);//函数设置与客户机断开是否会终止脚本的执行
if(!@include $cronfile) {
return false;
}
}
self::nextcron();//设置下次计划任务执行的时间,存入缓存
discuz_process::unlock($processname);
return true;
}
private static function nextcron() {
$cron = C::t('common_cron')->fetch_nextcron();
if($cron && isset($cron['nextrun'])) {
savecache('cronnextrun', $cron['nextrun']);
} else {
savecache('cronnextrun', TIMESTAMP + 86400 * 365);
}
return true;
}
/*
* 获取计划任务下次执行时间,更新此计划任务的上次执行时间,是否可用
*
*/
private static function setnextime($cron) {
if(empty($cron)) return FALSE;
list($yearnow, $monthnow, $daynow, $weekdaynow, $hournow, $minutenow) = explode('-', gmdate('Y-m-d-w-H-i', TIMESTAMP + getglobal('setting/timeoffset') * 3600));
//获取现在的年、月、日,周几,小时,分钟
if($cron['weekday'] == -1) {//为不限制
if($cron['day'] == -1) { //为不限制
$firstday = $daynow;//第一个日为今天, 第二个日为明天
$secondday = $daynow + 1;
} else {
$firstday = $cron['day']; //第一个日为计划任务指定的日,第二个日为计划任务指定的下一个月的日
$secondday = $cron['day'] + gmdate('t', TIMESTAMP + getglobal('setting/timeoffset') * 3600);
}
} else {
$firstday = $daynow + ($cron['weekday'] - $weekdaynow);//通过今天的日,计划任务的周几,现在的周几计划得出第一个日
$secondday = $firstday + 7; //第二个日
}
if($firstday < $daynow) {//如果超过了计划任务指定的,则为第二个日
$firstday = $secondday;
}
if($firstday == $daynow) { //计划任务的日为今天
$todaytime = self::todaynextrun($cron); //获取下次计划任务的小时,分钟
if($todaytime['hour'] == -1 && $todaytime['minute'] == -1) { //小时,分钟都无效
$cron['day'] = $secondday; //日为第二个日
$nexttime = self::todaynextrun($cron, 0, -1);
$cron['hour'] = $nexttime['hour'];
$cron['minute'] = $nexttime['minute'];
} else {
$cron['day'] = $firstday;
$cron['hour'] = $todaytime['hour'];
$cron['minute'] = $todaytime['minute'];
}
} else {
$cron['day'] = $firstday;
$nexttime = self::todaynextrun($cron, 0, -1);
$cron['hour'] = $nexttime['hour'];
$cron['minute'] = $nexttime['minute'];
}
//获取执行计划任务的下次时间 取得GMT日期的UNIX时间戳
$nextrun = @gmmktime($cron['hour'], $cron['minute'] > 0 ? $cron['minute'] : 0, 0, $monthnow, $cron['day'], $yearnow) - getglobal('setting/timeoffset') * 3600;
//如果计划任务下次执行的时间小于当前时间戳,则此计划任务无效
$data = array('lastrun' => TIMESTAMP, 'nextrun' => $nextrun);
if(!($nextrun > TIMESTAMP)) {
$data['available'] = '0';
}
C::t('common_cron')->update($cron['cronid'], $data);
return true;
}
/*
*
* 获取计划任务执行的小时,分钟
*/
private static function todaynextrun($cron, $hour = -2, $minute = -2) {
$hour = $hour == -2 ? gmdate('H', TIMESTAMP + getglobal('setting/timeoffset') * 3600) : $hour;
$minute = $minute == -2 ? gmdate('i', TIMESTAMP + getglobal('setting/timeoffset') * 3600) : $minute;
//没有设置小时,分钟值 是取当前的小时 ,分钟值
$nexttime = array();
if($cron['hour'] == -1 && !$cron['minute']) { //计划任务为任意小时,任意分钟
$nexttime['hour'] = $hour;
$nexttime['minute'] = $minute + 1;
} elseif($cron['hour'] == -1 && $cron['minute'] != '') { //计划任务为任意小时,指定分钟
$nexttime['hour'] = $hour;
if(($nextminute = self::nextminute($cron['minute'], $minute)) === false) { //如果分钟无效,即现在的分钟超过了指定分钟,则到下一个小时,分钟 为指定分钟的第一个值
++$nexttime['hour'];
$nextminute = $cron['minute'][0];
}
$nexttime['minute'] = $nextminute;
} elseif($cron['hour'] != -1 && $cron['minute'] == '') { //如果为指定小时,任意分钟
if($cron['hour'] < $hour) { //计划任务的小时小于当前小时
$nexttime['hour'] = $nexttime['minute'] = -1;
} elseif($cron['hour'] == $hour) { //计划任务的小时等于当前小时
$nexttime['hour'] = $cron['hour'];
$nexttime['minute'] = $minute + 1;
} else {
$nexttime['hour'] = $cron['hour'];
$nexttime['minute'] = 0;
}
} elseif($cron['hour'] != -1 && $cron['minute'] != '') { //如果为指定小时,指定分钟
$nextminute = self::nextminute($cron['minute'], $minute);
if($cron['hour'] < $hour || ($cron['hour'] == $hour && $nextminute === false)) {//计划任务小时小于当前小时,或者小时相等,但是分钟过了
$nexttime['hour'] = -1;
$nexttime['minute'] = -1;
} else {
$nexttime['hour'] = $cron['hour'];
$nexttime['minute'] = $nextminute;
}
}
return $nexttime;
}
private static function nextminute($nextminutes, $minutenow) {
foreach($nextminutes as $nextminute) {
if($nextminute > $minutenow) {
return $nextminute;
}
}
return false;
}
}
?>
|
|