Normalde web sitesinde rutin yapılan işlemler için sunucu (linux’tan bahsediyoruz) üzerinde cron işlemleri tanımlanır. Basit bir şekilde wget komutu yada doğrudan php komutu ile php dosyaları çalışıtırılarak işlem gerçekleştirilir.
Bu yukarıdaki durum ideal durum senaryosu, ve hiç şüphesiz dünya ideal değil 🙂 . İşte böyle durumlarda adına pseudo-cron denilen ve cron işlemlerini sitedeki sayfaların çağrılmasına bağlı olarak çalışan scriptlerle yerine getiren bir yöntem kullanılır. Zamanlama aylık günlük gibi ise problemsiz çalışabilecek bir yöntemdir. Özellikle web sitenizin durumunu izleyen bir de servis kullanıyorsanız, 1-2 saatlik aralarda bile sorunsuz çalışabilir.
WordPress de içinde WP-Cron Fonksiyonları diye bir grup pseudo-cron fonksiyonu barındırır.
Daha önceden bu gibi durumlar için kendi yazdığım bir şeyi kullanıyordum. Üzerinde fazla düşünülmemiş, o an için gereksinim gideren bir pseudo-cron yöntemiydi. Daha sonra ciddi olarak bir araştırma yapınca, uygun bir çözüm buldum. pseudo-cron adıyla (yaratıcı faaliyetten uzak bir isim :)) bir php scripti. Bu scriptin kullanımında da normal cron tanımlamasına benzer bir yöntem kullanılıyor.
Ben de bu scripti kullanarak bir CodeIgniter controller’ı oluşturdum.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 | <?php /* * * Tayfun Duran * http://tayfunduran.com * * modified from pseudo-cron v1.3 below * */ /* pseudo-cron v1.3 (c) 2003,2004 Kai Blankenhorn www.bitfolge.de/pseudocron kaib@bitfolge.de */ /* Kullanımı * 2 1,15 * * islem Yukarıdaki komut islem fonksiyonunu her ayın 1'inde ve 15'inde saat 02:00'de çalıştırır. */ class Cron extends CI_Controller { function gunluk(){ $this->load->model('mgenel', 'mayar'); $this->mayar->tablo = 'ayar'; $this->mayar->duzenle(null, array('kontrol' => 1)); } function __construct(){ parent::__construct(); /****************************************/ /* Ayarlar bölümü */ /****************************************/ // Her bir işlemi aşağıdaki diziye birer eleman olarak // ekleyiniz. Aşağıdaki komut her gece 00:00'de gunluk // fonsiyonunu çalıştırır. $this->cronTab = array( '00 * * * * gunluk', ); // Logların ve zamanlama bilgilerinin tutulacağı klasör. // Bu klasöre yazma izni olmalı. $this->writeDir = APPPATH . "logs/"; // Log tutulsun mu? $this->useLog = true; // Eposta adresi yazarsanız işlem sonucu gönderilir. // Sadece mail komutuyla gönderilen düşük seviyeli bir yöntemdir. $this->sendLogToEmail = ""; // pseudo-cron bir çağrılışında işletilecek görev sayısı // Eğer işlemler bir kaç saniyeden fazla sürüyorsa ve // birbirine çok yakın zamanlara ayarladıysanız düşük bir // sayı kullanınız. Sınır sayıda işlem için 0 yapın. $this->maxJobs = 1; // Hata çıktısını göstersin mi? // Yayındaki sunucularda kullanılması tavsiye edilmez. $this->debug = false; /****************************************/ /* buradan sonrasına dokunmayın */ /****************************************/ 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); $this->resultsSummary = ""; } function index(){ if ($this->debug) echo '<pre>'; $jobs = $this->_parseCronFile($this->cronTab); $jobsRun = 0; for ($i=0;$i<count($jobs);$i++) { if ($this->maxJobs==0 || $jobsRun<$this->maxJobs) { if ($this->_runJob($jobs[$i])) { $jobsRun++; } } } if ($this->debug) echo '</'.'pre>'; else{ header("Content-Type: image/gif"); echo base64_decode("R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="); } } function _logMessage($msg) { if ($msg[strlen($msg)-1]!="\n") { $msg.="\n"; } if ($this->debug) echo $msg; $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;$i<count($subelements);$i++) { if (preg_match("~^(\\*|([0-9]{1,2})(-([0-9]{1,2}))?)(/([0-9]{1,2}))?$~",$subelements[$i],$matches)) { for($i = 0; $i < 7; $i++) if(!isset($matches[$i])) $matches[$i] = ''; if ($matches[1]=="*") { $matches[2] = 0; // from $matches[4] = $numberOfElements; //to } elseif ($matches[4]=="") { $matches[4] = $matches[2]; } if (!isset($matches[5][0]) || $matches[5][0]!="/") { $matches[6] = 1; // step } for ($j=$this->_lTrimZeros($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; } } 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 ($lastScheduled<time()) { $this->_logMessage("Running ".$job[PC_CRONLINE]); $this->_logMessage(" Last run: ".date("r",$lastActual)); $this->_logMessage(" Last scheduled: ".date("r",$lastScheduled)); eval('$this->' . $job[PC_CMD] . '();'); $this->_markLastRun($job[PC_CMD], $lastScheduled); $this->_logMessage("Completed ".$job[PC_CRONLINE]); if ($this->sendLogToEmail!="") { mail($this->sendLogToEmail, "[cron] ".$job[PC_COMMENT], $this->resultsSummary); } return true; } else { if ($this->debug) { $this->_logMessage("Skipping ".$job[PC_CRONLINE]); $this->_logMessage(" Last run: ".date("r",$lastActual)); $this->_logMessage(" Last scheduled: ".date("r",$lastScheduled)); $this->_logMessage("Completed ".$job[PC_CRONLINE]); } return false; } } function _parseCronFile($cronTabFile) { $file = $cronTabFile; $job = Array(); $jobs = Array(); for ($i=0;$i<count($file);$i++) { if ($file[$i][0]!='#') { if (preg_match("~^([-0-9,/*]+)\\s+([-0-9,/*]+)\\s+([-0-9,/*]+)\\s+([-0-9,/*]+)\\s+([-0-7,/*]+|(-|/|Sun|Mon|Tue|Wed|Thu|Fri|Sat)+)\\s+([^#]*)\\s*(#.*)?$~i",$file[$i],$job)) { for($j = 0; $j < 21; $j++) if(!isset($job[$j])) $job[$j] = ''; $jobNumber = count($jobs); $jobs[$jobNumber] = $job; if ($jobs[$jobNumber][PC_DOW][0]!='*' AND !is_numeric($jobs[$jobNumber][PC_DOW])) { $jobs[$jobNumber][PC_DOW] = str_replace( Array("Sun","Mon","Tue","Wed","Thu","Fri","Sat"), Array(0,1,2,3,4,5,6), $jobs[$jobNumber][PC_DOW]); } $jobs[$jobNumber][PC_CMD] = trim($job[PC_CMD]); $jobs[$jobNumber][PC_COMMENT] = trim(substr($job[PC_COMMENT],1)); $jobs[$jobNumber][PC_CRONLINE] = $file[$i]; } $jobfile = $this->_getJobFileName($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; } } ?> |
Bu script bir gif resmi çıktısı verir. Yani sitenizde bu gif resmini yerleştirerek pseudo-cron’unuzu çalıştırabilirsiniz.
<img src="/cron" width="1" height="1" alt="" border="0" /> |
yada
<img src="/?c=cron" width="1" height="1" alt="" border="0" /> |
Yeni görevler eklemek için yapmanız gereken şey scriptin 46. satırındaki $this->cronTab dizi değişkenine yani elemanlar eklemek. Ve burada tanımlanmış olan fonksiyonu yine cron controller’ının içinde oluşturmak.
Bu resmi tek sayfaya yada her sayfaya koyabilirsiniz. Yalnız sayfanın en altına koymakda fayda var. Yine de sonuçta bu işlem siteye bir yüktür. Yapabildiğiniz sürece pseudo-cron değil gerçek cron jobs tanımlamaları yapmanızda büyük fayda var. Bu sadece cron job tanımlamaları yapamadığınız durumlarda çözüm olabilecek bir yoldur.
1 thought on “CodeIgniter Cron İşlemleri (cron jobs) için Pseudo-Cron Kullanımı”