EPESI BIM • Business Information Manager • Cloud CRM/ERP http://epe.si/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

135 lines
5.2 KiB

  1. <?php
  2. /**
  3. * This file provides cron functionality... Add it to your cron.
  4. * @author Paul Bukowski <pbukowski@telaxus.com>
  5. * @copyright Copyright &copy; 2006, Telaxus LLC
  6. * @license MIT
  7. * @version 1.0
  8. * @package epesi-base
  9. */
  10. define('CID',false);
  11. define('SET_SESSION',false);
  12. if (php_sapi_name() == 'cli') {
  13. define('EPESI_DIR', '/');
  14. if (isset($argv[1])) {
  15. define('DATA_DIR', $argv[1]);
  16. }
  17. } elseif (!isset($_GET['token'])) {
  18. die('Missing token in URL - please go to Administrator Panel->Cron and copy valid cron URL.');
  19. } else {
  20. defined("_VALID_ACCESS") || define("_VALID_ACCESS", true);
  21. require_once('include/include_path.php');
  22. require_once('include/data_dir.php');
  23. if(!file_exists(DATA_DIR.'/cron_token.php'))
  24. die('Invalid token in URL - please go to Administrator Panel->Cron and copy valid cron URL.');
  25. require_once(DATA_DIR.'/cron_token.php');
  26. if(CRON_TOKEN!=$_GET['token'])
  27. die('Invalid token in URL - please go to Administrator Panel->Cron and copy valid cron URL.');
  28. }
  29. require_once('include.php');
  30. $lock = DATA_DIR.'/cron.lock';
  31. if(file_exists($lock) && filemtime($lock)>time()-6*3600) die();
  32. register_shutdown_function(create_function('','@unlink("'.$lock.'");'));
  33. file_put_contents($lock,'');
  34. set_time_limit(0);
  35. ini_set('memory_limit', '512M');
  36. ModuleManager::load_modules();
  37. Base_AclCommon::set_sa_user();
  38. $ret = ModuleManager::call_common_methods('cron');
  39. $cron_last = DB::GetAssoc('SELECT func,last,running FROM cron ORDER BY last');
  40. $cron_funcs_prior = array(); //array of outdated cron callbacks
  41. $t = time();
  42. foreach($ret as $name=>$obj) {
  43. if(!$obj) continue;
  44. if(is_array($obj)) {
  45. foreach($obj as $func=>$every) {
  46. if(!strpos($func,'::')) $func = $name.'Common::'.$func;
  47. $func_md5 = md5($func);
  48. //if first cron run exists and it was executed in specified time or it keep running less then 24h - skip
  49. if(isset($cron_last[$func_md5]) && ($cron_last[$func_md5]['last']>$t-$every*60 || ($cron_last[$func_md5]['running'] && $cron_last[$func_md5]['last']>$t-min($every*60*30,24*60*60)))) continue;
  50. if(!isset($cron_last[$func_md5])) {
  51. DB::Execute('INSERT INTO cron(func,last,running,description) VALUES (%s,%d,%b,%s)',array($func_md5,0,0,$func));
  52. $cron_last = array_merge(array($func_md5 => array('last'=>0,'running'=>0)),$cron_last);
  53. }
  54. $cron_funcs_prior[$func_md5] = $func;
  55. }
  56. }
  57. }
  58. //print_r($cron_last);
  59. //print_r($cron_funcs_prior);
  60. function adodb_error() {}
  61. class CronErrorObserver extends ErrorObserver {
  62. private $func_md5;
  63. public function __construct($func_md5) {
  64. $this->func_md5 = $func_md5;
  65. }
  66. public function update_observer($type, $message, $errfile, $errline, $errcontext, $backtrace) {
  67. global $cron_funcs_prior;
  68. $backtrace = htmlspecialchars_decode(str_replace(array('<br />','&nbsp;'),array("\n",' '),$backtrace));
  69. $x = $cron_funcs_prior[$this->func_md5].":\ntype=".$type."\nmessage=".$message."\nerror file=".$errfile."\nerror line=".$errline."\n".$backtrace;
  70. error_log($x."\n",3,DATA_DIR.'/cron.txt');
  71. DB::IgnoreErrors(array('adodb_error',null)); //ignore adodb errors
  72. $query_args = array(time(),$this->func_md5);
  73. $query = DB::TypeControl('UPDATE cron SET last=%d,running=0 WHERE func=%s',$query_args);
  74. if(!DB::Execute($query,$query_args)) { //if not - probably server gone away - retry every 10 seconds for 1h
  75. for($i=0; $i<360; $i++) {
  76. sleep(10);
  77. $connection = null;
  78. try {
  79. $connection = DB::Connect(); //reconnect database as new connection
  80. } catch(Exception $e) {
  81. continue; //no connection - wait
  82. }
  83. if($connection->Execute($query,$query_args)) { //if ok then break and exit
  84. $connection->Close();
  85. break;
  86. }
  87. $connection->Close();
  88. }
  89. }
  90. return true;
  91. }
  92. }
  93. //call oldest executed callback
  94. foreach($cron_last as $func_md5=>$last) {
  95. if(!isset($cron_funcs_prior[$func_md5])) continue;
  96. DB::Execute('UPDATE cron SET last=%d,running=1 WHERE func=%s',array($t,$func_md5));
  97. @unlink($lock);
  98. // print('call '.$cron_funcs_prior[$func_md5]."\n");
  99. $error_handler = new CronErrorObserver($func_md5);
  100. ErrorHandler::add_observer($error_handler);
  101. ob_start();
  102. $output = array();
  103. try {
  104. $output[0] = call_user_func(explode('::',$cron_funcs_prior[$func_md5]));
  105. } catch(Exception $e) {
  106. $output[0] = $e->getMessage();
  107. }
  108. $output[1] = ob_get_clean();
  109. $output = array_filter($output);
  110. if($output) {
  111. $output = implode("<br />\n",$output);
  112. $stripped = $cron_funcs_prior[$func_md5].":\n".strip_tags($output)."\n\n";
  113. if(isset($argv))
  114. print($stripped);
  115. else
  116. print($cron_funcs_prior[$func_md5].":<br>".$output."<hr>");
  117. error_log($stripped,3,DATA_DIR.'/cron.txt');
  118. }
  119. DB::Execute('UPDATE cron SET last=%d,running=0 WHERE func=%s',array(time(),$func_md5));
  120. break;
  121. }
  122. @unlink($lock);