Discuz! X2 计划任务原理分析

举报
wh_bn 发表于 2021/12/16 00:53:17 2021/12/16
【摘要】 最近发现论坛内有些用户当月在线时间被清空,究其原因发现是清空当月在线时间的计划任务在某一错误时刻被执行。 就本帖分析下计划任务的实现过程,方便用户排查错误。 数据库结构: 论坛内现有的计划任务数据...
最近发现论坛内有些用户当月在线时间被清空,究其原因发现是清空当月在线时间的计划任务在某一错误时刻被执行。


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

数据库结构:

论坛内现有的计划任务数据被保存在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重新上传覆盖即可。

文章来源: blog.csdn.net,作者:fengda2870,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/fengda2870/article/details/40584315

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。