cron.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. <?php
  2. // Copyright (C) 2010-2012 Combodo SARL
  3. //
  4. // This file is part of iTop.
  5. //
  6. // iTop is free software; you can redistribute it and/or modify
  7. // it under the terms of the GNU Affero General Public License as published by
  8. // the Free Software Foundation, either version 3 of the License, or
  9. // (at your option) any later version.
  10. //
  11. // iTop is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU Affero General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU Affero General Public License
  17. // along with iTop. If not, see <http://www.gnu.org/licenses/>
  18. /**
  19. * Heart beat of the application (process asynchron tasks such as broadcasting email)
  20. *
  21. * @copyright Copyright (C) 2010-2012 Combodo SARL
  22. * @license http://opensource.org/licenses/AGPL-3.0
  23. */
  24. if (!defined('__DIR__')) define('__DIR__', dirname(__FILE__));
  25. require_once(__DIR__.'/../approot.inc.php');
  26. require_once(APPROOT.'/application/application.inc.php');
  27. require_once(APPROOT.'/application/nicewebpage.class.inc.php');
  28. require_once(APPROOT.'/application/webpage.class.inc.php');
  29. require_once(APPROOT.'/application/clipage.class.inc.php');
  30. require_once(APPROOT.'/application/startup.inc.php');
  31. function ReadMandatoryParam($oP, $sParam, $sSanitizationFilter = 'parameter')
  32. {
  33. $sValue = utils::ReadParam($sParam, null, true /* Allow CLI */, $sSanitizationFilter);
  34. if (is_null($sValue))
  35. {
  36. $oP->p("ERROR: Missing argument '$sParam'\n");
  37. UsageAndExit($oP);
  38. }
  39. return trim($sValue);
  40. }
  41. function UsageAndExit($oP)
  42. {
  43. $bModeCLI = utils::IsModeCLI();
  44. if ($bModeCLI)
  45. {
  46. $oP->p("USAGE:\n");
  47. $oP->p("php -q cron.php --auth_user=<login> --auth_pwd=<password> [--param_file=<file>] [--verbose=1]\n");
  48. }
  49. else
  50. {
  51. $oP->p("Optional parameters: verbose, param_file\n");
  52. }
  53. $oP->output();
  54. exit -2;
  55. }
  56. // Known limitation - the background process periodicity is NOT taken into account
  57. function CronExec($oP, $aBackgroundProcesses, $bVerbose)
  58. {
  59. $iStarted = time();
  60. $iMaxDuration = MetaModel::GetConfig()->Get('cron_max_execution_time');
  61. $iTimeLimit = $iStarted + $iMaxDuration;
  62. if ($bVerbose)
  63. {
  64. $oP->p("Planned duration = $iMaxDuration seconds");
  65. }
  66. $iCronSleep = MetaModel::GetConfig()->Get('cron_sleep');
  67. while (time() < $iTimeLimit)
  68. {
  69. foreach ($aBackgroundProcesses as $oBackgroundProcess)
  70. {
  71. if ($bVerbose)
  72. {
  73. $oP->p("Processing asynchronous task: ".get_class($oBackgroundProcess));
  74. }
  75. $sMessage = $oBackgroundProcess->Process($iTimeLimit);
  76. if ($bVerbose && !empty($sMessage))
  77. {
  78. $oP->p("Returned: $sMessage");
  79. }
  80. }
  81. if ($bVerbose)
  82. {
  83. $oP->p("Sleeping");
  84. }
  85. sleep($iCronSleep);
  86. }
  87. if ($bVerbose)
  88. {
  89. $oP->p("Reached normal execution time limit (exceeded by ".(time()-$iTimeLimit)."s)");
  90. }
  91. }
  92. ////////////////////////////////////////////////////////////////////////////////
  93. //
  94. // Main
  95. //
  96. if (utils::IsModeCLI())
  97. {
  98. $oP = new CLIPage("iTop - CRON");
  99. }
  100. else
  101. {
  102. $oP = new WebPage("iTop - CRON");
  103. }
  104. try
  105. {
  106. utils::UseParamFile();
  107. }
  108. catch(Exception $e)
  109. {
  110. $oP->p("Error: ".$e->GetMessage());
  111. $oP->output();
  112. exit -2;
  113. }
  114. if (utils::IsModeCLI())
  115. {
  116. // Next steps:
  117. // specific arguments: 'csvfile'
  118. //
  119. $sAuthUser = ReadMandatoryParam($oP, 'auth_user', 'raw_data');
  120. $sAuthPwd = ReadMandatoryParam($oP, 'auth_pwd', 'raw_data');
  121. if (UserRights::CheckCredentials($sAuthUser, $sAuthPwd))
  122. {
  123. UserRights::Login($sAuthUser); // Login & set the user's language
  124. }
  125. else
  126. {
  127. $oP->p("Access wrong credentials ('$sAuthUser')");
  128. $oP->output();
  129. exit -1;
  130. }
  131. }
  132. else
  133. {
  134. $_SESSION['login_mode'] = 'basic';
  135. require_once(APPROOT.'/application/loginwebpage.class.inc.php');
  136. LoginWebPage::DoLogin(); // Check user rights and prompt if needed
  137. }
  138. if (!UserRights::IsAdministrator())
  139. {
  140. $oP->p("Access restricted to administrators");
  141. $oP->Output();
  142. exit -1;
  143. }
  144. // Enumerate classes implementing BackgroundProcess
  145. //
  146. $aBackgroundProcesses = array();
  147. foreach(get_declared_classes() as $sPHPClass)
  148. {
  149. $oRefClass = new ReflectionClass($sPHPClass);
  150. $oExtensionInstance = null;
  151. if ($oRefClass->implementsInterface('iBackgroundProcess'))
  152. {
  153. if (is_null($oExtensionInstance))
  154. {
  155. $oExecInstance = new $sPHPClass;
  156. }
  157. $aBackgroundProcesses[$sPHPClass] = $oExecInstance;
  158. }
  159. }
  160. $bVerbose = utils::ReadParam('verbose', false, true /* Allow CLI */);
  161. if ($bVerbose)
  162. {
  163. $aDisplayProcesses = array();
  164. foreach ($aBackgroundProcesses as $oExecInstance)
  165. {
  166. $aDisplayProcesses[] = get_class($oExecInstance);
  167. }
  168. $sDisplayProcesses = implode(', ', $aDisplayProcesses);
  169. $oP->p("Background processes: ".$sDisplayProcesses);
  170. }
  171. $sLockName = 'itop.cron.php';
  172. $oP->p("Starting: ".time());
  173. $res = CMDBSource::QueryToScalar("SELECT GET_LOCK('$sLockName', 1)");// timeout = 1 second (see also IS_FREE_LOCK)
  174. if (is_null($res))
  175. {
  176. // TODO - Log ?
  177. $oP->p("ERROR: Failed to acquire the lock '$sLockName'");
  178. }
  179. elseif ($res === '1')
  180. {
  181. // The current session holds the lock
  182. try
  183. {
  184. CronExec($oP, $aBackgroundProcesses, $bVerbose);
  185. }
  186. catch(Exception $e)
  187. {
  188. // TODO - Log ?
  189. $oP->p("ERROR:".$e->GetMessage());
  190. }
  191. $res = CMDBSource::QueryToScalar("SELECT RELEASE_LOCK('$sLockName')");
  192. }
  193. else
  194. {
  195. // Lock already held by another session
  196. // Exit silently
  197. $oP->p("Already running...");
  198. }
  199. $oP->p("Exiting: ".time());
  200. $oP->Output();
  201. ?>