本帖最后由 ziwu85 于 2009-11-7 19:39 编辑
现象:
今天自己做了个计划任务,但是狂按立即执行,程序好像就是没有被执行的样子。
原因:
没办法只能自己分析程序,为什么不执行了。
一看程序才明白,原来S_ROOT.'./log/cron.lock.log'存在时,5分钟内禁止再执行任何计划任务了。
到相应位置一看,果然cron.lock.log存在。
可这个cron.lock.log又是怎么出来的呢?原来是在计划任务执行之前程序先要自动生成cron.lock.log,且在全部计划任务执行完毕再删除它(@unlink($lockfile);)。
而,我新写的计划任务有问题,执行了一半就停止了。导致cron.lock.log没有被自动删除掉。结果我5分钟内,拼命按立即执行我的代码也执行不到了。
另外,cron.lock.log的存在,不仅影响立即执行的功能,同样在这5分钟内自动执行的计划任务,也不会被执行了。
解决方法:
手工删除cron.lock.log文件后,再按立即执行就好使了。
评语:
这也许是康盛创想防止计划任务二次执行的一种手段。但,是否还能有更好的实现方法呢?或者说5分钟以后,计划任务还没有完成,是不是就能被二次执行了呢?
不知道官方是什么看法?
下面是ss7.0计划任务执行的核心函数的原版代码,给大家参考。- //执行计划任务,并更新计划任务CACHE
- function runcron($cronid = 0) {
- global $_SGLOBAL, $_SCONFIG, $_SBLOCK, $lang;
- //锁定
- $lockfile = S_ROOT.'./log/cron.lock.log';
- if(file_exists($lockfile)) {
- if($_SGLOBAL['timestamp'] - filemtime($lockfile) < 300) {//5分钟
- return;
- }
- }
- if(@$fp = fopen($lockfile, 'w')) {
- fwrite($fp, "\n");
- fclose($fp);
- }
- //读取cron列表缓存
- if(empty($_SGLOBAL['crons'])) return;
- @set_time_limit(1000);
- @ignore_user_abort(TRUE);
- $cronids = array();
- $crons = $cronid ? array($cronid => $_SGLOBAL['crons'][$cronid]) : $_SGLOBAL['crons'];
- if(empty($crons) || !is_array($crons)) return;
- foreach($crons as $id => $cron) {
- if($cron['nextrun'] <= $_SGLOBAL['timestamp'] || $id == $cronid) {
- $cronids[] = $id;
- if(!@include S_ROOT.($cronfile = "./include/cron/$cron[filename]")) {
- errorlog('CRON', $cron['name']." : Cron script($cronfile) not found or syntax error", 0);
- }
- }
- }
- cronnextrun($cronids);
- @unlink($lockfile);
- }
复制代码 |