The two files pseudo-cron.inc.php and pseudo-cron-image.php must be in the same directory on the server. The advantage of using this script is that pseudocron is called in a separate request and thus does not slow down output of the main page as it would if called from there. ***************************************************************************/ define("PC_MINUTE", 1); define("PC_HOUR", 2); define("PC_DOM", 3); define("PC_MONTH", 4); define("PC_DOW", 5); define("PC_CMD", 7); define("PC_COMMENT", 8); define("PC_CRONLINE", 20); // set some info about Dokuwiki define('DOKU_INC', realpath(dirname(__FILE__).'/../../../../').'/'); define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); //include("pseudo-cron.inc.php"); $cronojob = new cronojob(true); $cronojob->dojobs(); $cronojob->sendGif(); /*************************************************************************** pseudo-cron v1.3 (c) 2003,2004 Kai Blankenhorn www.bitfolge.de/pseudocron kaib@bitfolge.de This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. **************************************************************************** Usually regular tasks like backup up the site's database are run using cron jobs. With cron jobs, you can exactly plan when a certain command is to be executed. But most homepage owners can't create cron jobs on their web server – providers demand some extra money for that. The only thing that's certain to happen quite regularly on a web page are page requests. This is where pseudo-cron comes into play: With every page request it checks if any cron jobs should have been run since the previous request. If there are, they are run and logged. Pseudo-cron uses a syntax very much like the Unix cron's one. For an overview of the syntax used, see a page of the UNIXGEEKS. The syntax pseudo-cron uses is different from the one described on that page in the following points: - there is no user column - the executed command has to be an include()able file (which may contain further PHP code) All job definitions are made in a text file on the server with a user-definable name. A valid command line in this file is, for example: * 2 1,15 * * samplejob.inc.php This runs samplejob.inc.php at 2am on the 1st and 15th of each month. Features: - runs any PHP script - periodical or time-controlled script execution - logs all executed jobs - can be run from an IMG tag in an HTML page - follow Unix cron syntax for crontabs Usage: - Modify the variables in the config section below to match your server. - Write a PHP script that does the job you want to be run regularly. Be sure that any paths in it are relative to pseudo-cron. - Set up your crontab file with your script - put an include("pseudo-cron.inc.php"); statement somewhere in your most accessed page or call pseudo-cron-image.php from an HTML img tag - Wait for the next scheduled run :) Note: You can log messages to pseudo-cron's log file from cron jobs by calling $this->logMessage("log a message"); Release notes for v1.2.2: This release changed the way cron jobs are called. The file paths you specify in the crontab file are now relative to the location of pseudo-cron.inc.php, instead of to the calling script. Example: If /include/pseudo-cron.inc.php is included in /index.php and your cronjobs are in /include/cronjobs, then your crontab file looked like this: 10 1 * * * include/cronjobs/dosomething.php # do something Now you have to change it to 10 1 * * * cronjobs/dosomething.php # do something After you install the new version, each of your cronjobs will be run once, and the .job files will have different names than before. ***************************************************************************/ // || PLEASE NOTE: // || all paths used here and in cron scripts // || must be absolute or relative to pseudo-cron.inc.php! // || // || To easily use absolute paths, have a look at how the // || crontab location is defined below. class cronojob { /****************************************/ /* config section */ /****************************************/ // The string that contains the job descriptions. // One job for line // #scheduled jobs // #comments start with # // #mi h d m dow job comment'; // For a description of the format, see http://www.unixgeeks.org/security/newbie/unix/cron-1.html // and http://www.bitfolge.de/pseudocron var $cronTab; // The directory where the script can store information on completed jobs and its log file. // include trailing slash var $writeDir; // Control logging, true=use log file, false=don't use log file var $useLog; // Where to send cron results. var $sendLogToEmail; // Maximum number of jobs run during one call of pseudocron. // Set to a low value if your jobs take longer than a few seconds and if you scheduled them // very close to each other. Set to 0 to run any number of jobs. var $maxJobs = 1; // Turn on / off debugging output // DO NOT use this on live servers! var $debug = false; /****************************************/ /* don't change anything here */ /****************************************/ var $resultsSummary; var $pluginname; var $dokuwikititle; function cronojob($debug = false) { $this->debug = $debug; $this->writeDir = DOKU_INC."data/tmp/"; $this->pluginname = "cronojob"; // legge la configurazione $path = DOKU_PLUGIN.$this->pluginname.'/conf/'; $conf = array(); if (@file_exists($path.'default.php')) { include($path.'default.php'); } $conf_plug = $conf; $path = DOKU_INC.'conf/'; $conf = array(); if (@file_exists($path.'local.php')) { include($path.'local.php'); } $this->dokuwikititle = $conf['title']; foreach ($conf_plug as $key => $value) { if (isset($conf['plugin'][$this->pluginname][$key])) $conf_plug[$key] = $conf['plugin'][$this->pluginname][$key]; } // legge la configurazione $this->cronTab = $conf_plug['cronotab']; $this->sendLogToEmail = $conf_plug['email']; if ($conf_plug['maxjobs'] > 0) $this->maxjobs = $conf_plug['maxjobs']; $this->useLog = $conf_plug['uselog']; } function dojobs() { if ($this->debug) echo "
";
    $jobs = $this->parseCronFile($this->cronTab);
    $jobsRun = 0;
    for ($i=0;$imaxJobs==0 || $jobsRun<$this->maxJobs) {
        if ($this->runJob($jobs[$i])) $jobsRun++;
      }
    }
    if ($this->debug) echo "
"; } function logMessage($msg) { if ($msg[strlen($msg)-1]!="\n") { $msg.="\n"; } if ($this->debug) echo $msg." ".$this->useLog; $this->resultsSummary.= $msg; if ($this->useLog) { $logfile = $this->writeDir."pseudo-cron.log"; $file = fopen($logfile,"a"); fputs($file,date("r",time())." ".$msg); fclose($file); } } function lTrimZeros($number) { while ($number[0]=='0') { $number = substr($number,1); } return $number; } function multisort(&$array, $sortby, $order='asc') { foreach($array as $val) { $sortarray[] = $val[$sortby]; } $c = $array; $const = $order == 'asc' ? SORT_ASC : SORT_DESC; $s = array_multisort($sortarray, $const, $c, $const); $array = $c; return $s; } function parseElement($element, &$targetArray, $numberOfElements) { $subelements = explode(",",$element); for ($i=0;$i<$numberOfElements;$i++) { $targetArray[$i] = $subelements[0]=="*"; } for ($i=0;$ilTrimZeros($matches[2]);$j<=$this->lTrimZeros($matches[4]);$j+=$this->lTrimZeros($matches[6])) { $targetArray[$j] = TRUE; } } } } function incDate(&$dateArr, $amount, $unit) { if ($this->debug) echo sprintf("Increasing from %02d.%02d. %02d:%02d by %d %6s ",$dateArr[mday],$dateArr[mon],$dateArr[hours],$dateArr[minutes],$amount,$unit); if ($unit=="mday") { $dateArr["hours"] = 0; $dateArr["minutes"] = 0; $dateArr["seconds"] = 0; $dateArr["mday"] += $amount; $dateArr["wday"] += $amount % 7; if ($dateArr["wday"]>6) { $dateArr["wday"]-=7; } $months28 = Array(2); $months30 = Array(4,6,9,11); $months31 = Array(1,3,5,7,8,10,12); if ( (in_array($dateArr["mon"], $months28) && $dateArr["mday"]==28) || (in_array($dateArr["mon"], $months30) && $dateArr["mday"]==30) || (in_array($dateArr["mon"], $months31) && $dateArr["mday"]==31) ) { $dateArr["mon"]++; $dateArr["mday"] = 1; } } elseif ($unit=="hour") { if ($dateArr["hours"]==23) { $this->incDate($dateArr, 1, "mday"); } else { $dateArr["minutes"] = 0; $dateArr["seconds"] = 0; $dateArr["hours"]++; } } elseif ($unit=="minute") { if ($dateArr["minutes"]==59) { $this->incDate($dateArr, 1, "hour"); } else { $dateArr["seconds"] = 0; $dateArr["minutes"]++; } } if ($this->debug) echo sprintf("to %02d.%02d. %02d:%02d\n",$dateArr[mday],$dateArr[mon],$dateArr[hours],$dateArr[minutes]); } function getLastScheduledRunTime($job) { $extjob = Array(); $this->parseElement($job[PC_MINUTE], $extjob[PC_MINUTE], 60); $this->parseElement($job[PC_HOUR], $extjob[PC_HOUR], 24); $this->parseElement($job[PC_DOM], $extjob[PC_DOM], 31); $this->parseElement($job[PC_MONTH], $extjob[PC_MONTH], 12); $this->parseElement($job[PC_DOW], $extjob[PC_DOW], 7); $dateArr = getdate($this->getLastActualRunTime($job[PC_CMD])); $minutesAhead = 0; while ( $minutesAhead<525600 AND (!$extjob[PC_MINUTE][$dateArr["minutes"]] OR !$extjob[PC_HOUR][$dateArr["hours"]] OR (!$extjob[PC_DOM][$dateArr["mday"]] OR !$extjob[PC_DOW][$dateArr["wday"]]) OR !$extjob[PC_MONTH][$dateArr["mon"]]) ) { if (!$extjob[PC_DOM][$dateArr["mday"]] OR !$extjob[PC_DOW][$dateArr["wday"]]) { $this->incDate($dateArr,1,"mday"); $minutesAhead+=1440; continue; } if (!$extjob[PC_HOUR][$dateArr["hours"]]) { $this->incDate($dateArr,1,"hour"); $minutesAhead+=60; continue; } if (!$extjob[PC_MINUTE][$dateArr["minutes"]]) { $this->incDate($dateArr,1,"minute"); $minutesAhead++; continue; } } //if ($this->debug) print_r($dateArr); return mktime($dateArr["hours"],$dateArr["minutes"],0,$dateArr["mon"],$dateArr["mday"],$dateArr["year"]); } function getJobFileName($jobname) { $jobfile = $this->writeDir.urlencode($jobname).".job"; return $jobfile; } function getLastActualRunTime($jobname) { $jobfile = $this->getJobFileName($jobname); if (file_exists($jobfile)) { return filemtime($jobfile); } return 0; } function markLastRun($jobname, $lastRun) { $jobfile = $this->getJobFileName($jobname); touch($jobfile); } function runJob($job) { $this->resultsSummary = ""; $lastActual = $job["lastActual"]; $lastScheduled = $job["lastScheduled"]; if ($lastScheduledlogMessage("Running ".$job[PC_CRONLINE]); $this->logMessage(" Last run: ".date("r",$lastActual).", Last scheduled: ".date("r",$lastScheduled)); $e = @error_reporting(0); if ($this->debug) { include(DOKU_PLUGIN.$this->pluginname."/jobs/".$job[PC_CMD]); // display errors only when debugging } else { @include(DOKU_PLUGIN.$this->pluginname."/jobs/".$job[PC_CMD]); // any error messages are supressed } @error_reporting($e); $this->markLastRun($job[PC_CMD], $lastScheduled); $this->logMessage(" Completed ".$job[PC_CRONLINE]); if ($this->sendLogToEmail!="") { mail($this->sendLogToEmail, "[".$this->dokuwikititle."][".$this->pluginname."] ".$job[PC_COMMENT], $this->resultsSummary); } return true; } else { if ($this->debug) { $this->logMessage("Skipping ".$job[PC_CRONLINE]); $this->logMessage(" Last run: ".date("r",$lastActual).", Last scheduled: ".date("r",$lastScheduled)); $this->logMessage(" Completed ".$job[PC_CRONLINE]); } return false; } } function parseCronFile($cronTabFile) { $file = explode("\n", $cronTabFile); // $file = file($cronTabFile); // $file = $cronTabFile; $job = Array(); $jobs = Array(); for ($i=0;$igetJobFileName($jobs[$jobNumber][PC_CMD]); $jobs[$jobNumber]["lastActual"] = $this->getLastActualRunTime($jobs[$jobNumber][PC_CMD]); $jobs[$jobNumber]["lastScheduled"] = $this->getLastScheduledRunTime($jobs[$jobNumber]); } } $this->multisort($jobs, "lastScheduled"); if ($this->debug) var_dump($jobs); return $jobs; } function sendGif() { if($this->debug) return; /* $img = base64_decode("iVBORw0KGgoAAAANSUhEUgAAAFAAAAAPCAIAAAD8q9/YAAAA5ElEQVRIieVXuw7DIAw8qnwrnrt0 4AM6sDD7a+lAQylg4kp5VOIm63TINucYxVhrMRMWAMx8dRkngYiWNTQ/n+bog9u3oEPxuD8B3K4u 42xM1/DS4Ti+g3LOEylMfpoWAOWQJzIzSo0UVwc3Nd10EB0mAzKfzjnWTAMfnA8up0mllIxSU8YD mUbTPdVzGLKf8m6TTBj42UUqcZd12L2gocMtthweZ1W2MTYTQifKkgSHK+RhVr9euegqZWmgpMF3 z61Mw0AYKGOtZeZJ3mEimu5Zmq7h9RuWt9EAyuXxVzCz/S29AGJYqkfnR9EBAAAAAElFTkSuQmCC"); */ $img = base64_decode("R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="); Header("Content-Type: image/gif"); Header('Content-Length: '.strlen($img)); header('Connection: Close'); echo $img; } } ?>