Discuz! 官方站

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 23466|回复: 7

Discuz! X2 计划任务原理分析

[复制链接]
发表于 2011-7-27 16:13:21 | 显示全部楼层 |阅读模式
本帖最后由 nxy105 于 2011-7-27 16:14 编辑

最近发现论坛内有些用户当月在线时间被清空,究其原因发现是清空当月在线时间的计划任务在某一错误时刻被执行。


就本帖分析下计划任务的实现过程,方便用户排查错误。

数据库结构:

论坛内现有的计划任务数据被保存在pre_common_cron表中,表中数据与论坛后台计划任务列表中的数据一致。
weekday字段为X表示每周星期X执行计划任务,day字段为X表示每月X日执行计划任务。X为-1表示不限制,即每天都执行计划任务。

执行计划任务:

执行计划任务在class_core.php中,初始化计划任务的函数_init_cron()中

  1. function _init_cron() {
  2.                 $ext = empty($this->config['remote']['on']) || empty($this->config['remote']['cron']) || APPTYPEID == 200;
  3.                 if($this->init_cron && $this->init_setting && $ext) {
  4.                         if($this->var['cache']['cronnextrun'] <= TIMESTAMP) {//判断当前是否有计划任务出于待执行状态
  5.                                 require_once libfile('class/cron');
  6.                                 discuz_cron::run();//执行计划任务
  7.                         }
  8.                 }
  9.         }
复制代码

计划任务执行函数discuz_cron::run()

  1. function run($cronid = 0) {

  2.                 global $_G;
  3.                 $timestamp = TIMESTAMP;
  4.                 $cron = DB::fetch_first("SELECT * FROM ".DB::table('common_cron')."
  5.                                 WHERE ".($cronid ? "cronid='$cronid'" : "available>'0' AND nextrun<='$timestamp'")."
  6.                                 ORDER BY nextrun LIMIT 1"); //取出一条符合执行条件的计划任务

  7.                 $processname ='DZ_CRON_'.(empty($cron) ? 'CHECKER' : $cron['cronid']);

  8.                 if($cronid && !empty($cron)) { //为了手动执行计划任务解锁
  9.                         discuz_process::unlock($processname);
  10.                 }

  11.                 if(discuz_process::islocked($processname, 600)) { //检查计划任务进程是否上锁
  12.                         return false;
  13.                 }

  14.                 if($cron) {  //计划任务执行部分

  15.                         $cron['filename'] = str_replace(array('..', '/', '\\'), '', $cron['filename']);
  16.                         $cronfile = DISCUZ_ROOT.'./source/include/cron/'.$cron['filename'];

  17.                         $cron['minute'] = explode("\t", $cron['minute']);
  18.                         discuz_cron::setnextime($cron); //根据后台设置,更新该计划任务执行的时间

  19.                         @set_time_limit(1000);
  20.                         @ignore_user_abort(TRUE); //设置与客户机断开不会终止脚本的执行

  21.                         if(!@include $cronfile) { //执行具体计划任务程序
  22.                                 return false;
  23.                         }
  24.                 }

  25.                 discuz_cron::nextcron(); //设置最近一次计划任务执行的时间
  26.                 discuz_process::unlock($processname); //解锁进程
  27.                 return true;
  28.         }
复制代码

注意:
每一个入口文件,如forum.php,space.php都有计划任务执行的入口,但打开一次页面只执行一条计划任务。

总结:
计划任务涉及的文件并不多,如果计划任务出现异常,通常只需要将class_core.php,class_cron.php重新上传覆盖即可。
发表于 2011-7-27 16:28:08 | 显示全部楼层
支持一下下

评分

1

查看全部评分

回复

使用道具 举报

发表于 2011-9-8 15:08:08 | 显示全部楼层
回复

使用道具 举报

发表于 2011-9-16 12:04:34 | 显示全部楼层
借鉴一下
回复

使用道具 举报

发表于 2011-9-20 10:19:07 | 显示全部楼层
学习了
回复

使用道具 举报

发表于 2011-10-19 15:35:02 | 显示全部楼层
支持一下了
回复

使用道具 举报

发表于 2011-10-19 20:51:49 | 显示全部楼层
:    $
回复

使用道具 举报

发表于 2012-1-9 13:29:56 | 显示全部楼层
感谢 又了解了一些
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

腾讯云「工商注册服务」全新上线!全场低至10元起,一站搞定工商服务,让创业起步更轻松

小黑屋|Discuz! 官方站 ( 粤B2-20090059-165 )star

GMT+8, 2020-9-22 21:34

Powered by Discuz! X3.3

Copyright © 2001-2019 Tencent Cloud.

快速回复 返回顶部 返回列表