禅道管理系统的定时任务 代码

发表于:2018-8-03 10:30

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:sdcxyz    来源:CSDN

  禅道管理系统里面有一些定时任务的,例如更新燃尽图,定时备份数据库等。
  昨天我发现禅道不能登录了,检查了一下发现禅道所在的目录没有空间了,排查了一下发现是禅道的定时任务每天备份数据库文件还有上传的附件,由于附件很大所以每天都占用大量的存储空间。
  然后我删掉了那些多余的备份,另外想禁用掉禅道的自动备份。然后问题来了
  禅道的定时任务是如何执行的呢?
  首先想到的是crontab,因为禅道官网提供了一些脚本用来做这些操作的,它就生成了一些sh脚本,需要添加到cron里面,然后就可以定时执行了
  问题是我检查了所有用的crontab,发现并没有禅道的任何定时任务项目。
  这引起了我的好奇心,我决定追入禅道的代码看看究竟是什么原因使得禅道有了自动定时任务的功能
  /**
  *Ajaxexeccron.
  *
  *@accesspublic
  *@returnvoid
  */
  publicfunctionajaxExec()
  {
  ignore_user_abort(true);
  set_time_limit(0);
  session_write_close();
  /*Checkcronturnon.*/
  if(empty($this->config->global->cron))die();
  /*makecronstatustorunning.*/
  $configID=$this->cron->getConfigID();
  $configID=$this->cron->markCronStatus('running',$configID);
  /*Getandparsecrons.*/
  $crons=$this->cron->getCrons('nostop');
  $parsedCrons=$this->cron->parseCron($crons);
  /*Updatelasttime.*/
  $this->cron->changeStatus(key($parsedCrons),'normal',true);
  $this->loadModel('common');
  $startedTime=time();
  while(true)
  {
  /*Whencronisnullthendie.*/
  if(empty($crons))break;
  if(empty($parsedCrons))break;
  if(!$this->cron->getTurnon())break;
  /*Runcrons.*/
  $now=newdatetime('now');
  $this->common->loadConfigFromDB();
  foreach($parsedCronsas$id=>$cron)
  {
  $cronInfo=$this->cron->getById($id);
  /*Skipemptyandstopcron.*/
  if(empty($cronInfo)or$cronInfo->status=='stop')continue;
  /*Skipcronthatstatusisrunningandruntimeislessthanmax.*/
  if($cronInfo->status=='running'and(time()-strtotime($cronInfo->lastTime))<$this->config->cron->maxRunTime)continue;
  /*Skipcronthatlasttimeismorethanthiscrontime.*/
  if($cronInfo->lastTime>$cron['time']->format(DT_DATETIME1))die();
  if($now>$cron['time'])
  {
  $this->cron->changeStatus($id,'running');
  $parsedCrons[$id]['time']=$cron['cron']->getNextRunDate();
  /*Executioncommand.*/
  $output='';
  $return='';
  if($cron['command'])
  {
  if(isset($crons[$id])and$crons[$id]->type=='zentao')
  {
  parse_str($cron['command'],$params);
  if(isset($params['moduleName'])andisset($params['methodName']))
  {
  $this->app->loadConfig($params['moduleName']);
  $output=$this->fetch($params['moduleName'],$params['methodName']);
  }
  }
  elseif(isset($crons[$id])and$crons[$id]->type=='system')
  {
  exec($cron['command'],$output,$return);
  if($output)$output=join("\n",$output);
  }
  /*Savelog.*/
  $log='';
  $time=$now->format('G:i:s');
  $log="$timetask".$id."executed,\ncommand:$cron[command].\nreturn:$return.\noutput:$output\n";
  $this->cron->logCron($log);
  unset($log);
  }
  /*Revertcronstatus.*/
  $this->cron->changeStatus($id,'normal');
  }
  }
  /*Checkwhetherthetaskchange.*/
  $newCrons=$this->cron->getCrons('nostop');
  $changed=$this->cron->checkChange();
  if(count($newCrons)!=count($crons)or$changed)
  {
  $crons=$newCrons;
  $parsedCrons=$this->cron->parseCron($newCrons);
  }
  /*Sleepsomeseconds.*/
  $sleepTime=60-((time()-$now->getTimestamp())%60);//注意这里,sleep睡觉小于60秒
  sleep($sleepTime);
  /*Breakwhile.*/
  if(connection_status()!=CONNECTION_NORMAL)break;
  if(((time()-$startedTime)/3600/24)>=$this->config->cron->maxRunDays)break;
  }
  /*Revertcronstatustostop.*/
  $this->cron->markCronStatus('stop',$configID);
  }
  这段代码是被footer.html.php文件里面的代码执行的
  这段js代码是被浏览器执行的,但是因为已经有一个死循环在服务端执行了,如果这段代码被多次执行,完全是浪费服务器资源,禅道是如何避免多次执行的呢
  if($this->loadModel('cron')->runable())js::execute('startCron()');
  还是刚才footer文件里面的代码,意思是如果cron模块是可运行的,才执行那个ajaxcron代码,继续看runable的代码
  publicfunctionrunable()
  {
  if(empty($this->config->global->cron))returnfalse;
  $lastTime=$this->getLastTime();
  if($lastTime=='0000-00-0000:00:00'or((time()-strtotime($lastTime))>$this->config->cron->maxRunTime))returntrue;
  if(!isset($this->config->cron->run->status))returntrue;
  if($this->config->cron->run->status=='stop')returntrue;
  returnfalse;
  }
  $lastTime是cron表里面lastTime最新时间的值(没错,这个表里面的时间一直被上面所说的循环update),上面的代码是如果cron表里面最新的时间离现在已经超过<prename="code"class="php">maxRunTime(配置文件里面写的,是65秒),如果已经超过65秒了,那么认为是服务端那个死循环的php执行已经被停止了,就会自动在发起一个ajaxcron的请求。
  禅道就是这么避免这个死循环被多次在执行的。也是通过这些代码来使得即使你没有配置系统的crontab,依然可以执行定时任务,这是个不错的思路。
   上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号