discuz X2计划任务

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


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

数据库结构:

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

执行计划任务:

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

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

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

function run($cronid = 0) {

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

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

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

                if(discuz_process::islocked($processname, 600)) { //检查计划任务进程是否上锁
                        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']);
                        discuz_cron::setnextime($cron); //根据后台设置,更新该计划任务执行的时间

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

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

                discuz_cron::nextcron(); //设置最近一次计划任务执行的时间
                discuz_process::unlock($processname); //解锁进程
                return true;
        }

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

总结:
计划任务涉及的文件并不多,如果计划任务出现异常,通常只需要将class_core.php,class_cron.php重新上传覆盖即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值