Overview

Namespaces

  • Cron
  • None

Classes

  • _HtmlGrid_TableOut
  • _TransactionModel_RawSaveOperation
  • AccessControlComponent
  • AccessControlHelper
  • ActionListHelper
  • ActiveDirectoryUtils
  • AddCurrentPidToSchedulingShellCallLogs
  • AnonymousFunctionOperation
  • ArrayUtil
  • AssociationIntegrityBehavior
  • AtomicOperation
  • AuthenticationComponent
  • AuthenticationController
  • AuthenticationUser
  • AutocompleteDatasourceComponent
  • BaseModelComponent
  • Basics
  • CakeLayersHelper
  • CheckAndRunShell
  • ClassSearcher
  • CommandLineUtil
  • CommonValidationBehavior
  • ConfigurableShellCallsSchedulingTask
  • ConfigurationKey
  • ConfigurationKeys
  • ConfigurationKeysController
  • Context
  • ContextComponent
  • ContextHelper
  • Contexts
  • ControllerInspector
  • ControllerMenuHelper
  • CreateJournalingTables
  • CreateTableConfigurationKeys
  • CreateTableSchedulingConfigurableShellCalls
  • CreateTableSchedulingShellCallLogs
  • CreateTableSettedConfigurationKeys
  • CreateTableUserResetPasswordRequests
  • CreateTableUsers
  • CronSchedulingInstaller
  • CronValidationBehavior
  • CssBox
  • CssController
  • CssProperties
  • CssShell
  • CsvUtil
  • CustomDataModel
  • DatasourceDumperManager
  • DateTimeInput
  • DependencyShell
  • DetailHelper
  • DumperShell
  • ExtendedFieldsAccessControl
  • ExtendedFieldSet
  • ExtendedFieldSetHelper
  • ExtendedFieldsParser
  • ExtendedFormHelper
  • ExtendedHasManyAppModel
  • ExtendedOperationsBehavior
  • FieldDefinition
  • FieldRowDefinition
  • FieldSetDefinition
  • FieldSetLayoutHelper
  • FileOperations
  • FileOperations_Rename
  • FileOperations_SymLink
  • FileOperations_Touch
  • FileOperations_Unlink
  • FileSystem
  • FixConfigurationKeysPrimaryKey
  • FixSettedConfigurationKeysPrimaryKey
  • HasManyUtilsBehavior
  • HtmlDocument
  • HtmlGrid
  • HtmlGrid_Cell
  • HttpClient
  • HttpResponse
  • ImapClient
  • ImapMailBox
  • ImapParserShell
  • IncludePath
  • InputMasked
  • InputSearchable
  • InputsOnSubmit
  • InstallShell
  • JenkinsBuildShell
  • Journal
  • JournalDetail
  • JournalizedBehavior
  • JsonResponseComponent
  • LayoutsHelper
  • Ldap
  • LdapUtils
  • ListFieldSet
  • ListFieldSetHelper
  • ListsHelper
  • MailParser
  • Make
  • MenuHelper
  • MigrationAllPluginsShell
  • ModelOperations
  • ModelOperations_Delete
  • ModelOperations_Save
  • ModelTraverser
  • MysqlDumper
  • OpenLdapUtils
  • PaginatorUtilComponent
  • PaginatorUtilComponentFilter
  • PaginatorUtilHelper
  • Plugin
  • PluginManager
  • Reflections
  • RenameEnabledToActiveFromUsersTable
  • RunShellCallShell
  • ScaffoldUtilComponent
  • ScaffoldUtilHelper
  • Scheduling
  • SchedulingConfigurableShellCall
  • SchedulingConfigurableShellCallsController
  • SchedulingShellCallLog
  • SchedulingShellCallLogsController
  • SettedConfigurationKey
  • StuffreposPluginsRename
  • TimeZoneBehavior
  • TransactionModel
  • TransactionOperation
  • Translator
  • TranslatorShell
  • User
  • UserAuthenticationComponent
  • UserChangePassword
  • UserResetPassword
  • UserResetPasswordRequest
  • UserResetPasswordRequestSubmission
  • UsersController
  • ViewUtilHelper

Interfaces

  • AccessControlFilter
  • CommitableOperation
  • DatasourceDumper
  • MakeListener
  • SchedulingInstaller
  • TasksObject
  • UndoableOperation

Exceptions

  • LdapObjectNotWritableException
  • ModelTraverserException
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: 
  3: App::uses('Scheduling', 'Scheduling.Lib');
  4: 
  5: class CheckAndRunShell extends Shell {
  6: 
  7:     const SCHEDULING_STATE_RUN = 'run';
  8:     const SCHEDULING_STATE_PASS = 'pass';
  9:     const SCHEDULING_STATE_SET_NEXT_RUN = 'set_next_run';
 10:     const SCHEDULING_STATE_TIMEOUT = 'timeout';
 11:     const PROCESS_TIMEOUT = 3600;
 12: 
 13:     public $uses = array(
 14:         'Scheduling.SchedulingShellCallLog',
 15:     );
 16: 
 17:     public function getOptionParser() {
 18:         $parser = parent::getOptionParser();
 19:         $parser->addOption('ignore-scheduling', array(
 20:             'boolean' => true
 21:         ));
 22:         return $parser;
 23:     }
 24: 
 25:     public function main() {
 26:         foreach (Scheduling::shellCalls() as $shellCall) {
 27:             $this->_checkShellCall($shellCall);
 28:         }
 29:     }
 30: 
 31:     private function _checkShellCall($shellCall) {
 32:         $this->out('<info>Shell call: </info>' . $this->_shellCallToString($shellCall));
 33:         $schedulingShellCallLog = Scheduling::findLog($shellCall);
 34:         $this->out("  * Next run: " . (empty($schedulingShellCallLog['SchedulingShellCallLog']['next_run']) ? 'Not set' : $schedulingShellCallLog['SchedulingShellCallLog']['next_run']));
 35:         $currentTimestamp = time();
 36:         $this->out("  * Current: " . date('Y-m-d H:i:s', $currentTimestamp));
 37:         switch ($this->_schedulingState($schedulingShellCallLog, $currentTimestamp)) {
 38:             case self::SCHEDULING_STATE_RUN:
 39:                 $this->_runShellCall($schedulingShellCallLog);
 40:                 break;
 41: 
 42:             case self::SCHEDULING_STATE_TIMEOUT:
 43:                 $this->_killProcess($schedulingShellCallLog);
 44:                 $this->_runShellCall($schedulingShellCallLog);
 45:                 break;
 46: 
 47:             case self::SCHEDULING_STATE_SET_NEXT_RUN:
 48:                 $this->out('  * Setting next run...');
 49:                 Scheduling::setNextRun($schedulingShellCallLog['SchedulingShellCallLog']);
 50:                 break;
 51: 
 52:             case self::SCHEDULING_STATE_PASS:
 53:                 $this->out('  * Pass');
 54:                 break;
 55:         }
 56:         $this->out('  * Done');
 57:     }
 58: 
 59:     private function _schedulingState($schedulingShellCallLog, $currentTimestamp) {
 60:         if (!$schedulingShellCallLog['SchedulingShellCallLog']['next_run']) {
 61:             return self::SCHEDULING_STATE_SET_NEXT_RUN;
 62:         }
 63:         $nextRun = strtotime($schedulingShellCallLog['SchedulingShellCallLog']['next_run']);
 64:         if ($nextRun <= $currentTimestamp || $this->params['ignore-scheduling']) {
 65:             $currentPid = $schedulingShellCallLog['SchedulingShellCallLog']['current_pid'];
 66:             if ($currentPid) {
 67:                 $processAge = $this->_currentProcessLifeTime($currentPid);
 68:                 if ($processAge === false) {
 69:                     return self::SCHEDULING_STATE_RUN;
 70:                 } else if ($processAge > self::PROCESS_TIMEOUT) {
 71:                     return self::SCHEDULING_STATE_TIMEOUT;
 72:                 } else {
 73:                     return self::SCHEDULING_STATE_PASS;
 74:                 }
 75:             }
 76:             return self::SCHEDULING_STATE_RUN;
 77:         }
 78:         return self::SCHEDULING_STATE_PASS;
 79:     }
 80: 
 81:     private function _runShellCall($schedulingShellCallLog) {
 82:         $this->out('  * Running...');
 83:         $command = self::_shellCallCommand($schedulingShellCallLog);
 84:         $this->out("  * Command: $command");
 85:         $pid = $this->_execInBackground($command);
 86:         $this->out("  * PID: $pid");
 87:         $this->out("  * Storing process id...");
 88:         $this->_storeProcessId($schedulingShellCallLog, $pid);
 89:     }
 90: 
 91:     private function _storeProcessId($schedulingShellCallLog, $pid) {
 92:         ClassRegistry::init('SchedulingShellCallLog')->saveOrThrowException(array(
 93:             'SchedulingShellCallLog' => array(
 94:                 'id' => $schedulingShellCallLog['SchedulingShellCallLog']['id'],
 95:                 'current_pid' => $pid
 96:             )
 97:                 )
 98:         );
 99:     }
100: 
101:     private function _currentProcessLifeTime($pid) {
102:         if (substr(php_uname(), 0, 7) == "Windows") {
103:             return $this->_currentProcessLifeTimeWindows($pid);
104:         } else {
105:             return $this->_currentProcessLifeTimeDefault($pid);
106:         }
107:     }
108: 
109:     private function _currentProcessLifeTimeDefault($pid) {
110:         exec("ps -p $pid -o lstart=", $output);
111:         if (empty($output)) {
112:             return false;
113:         } else {
114:             return time() - strtotime($output[0]);
115:         }
116:     }
117: 
118:     private function _killProcess($schedulingShellCallLog) {
119:         $this->out('  * Killing process ' . $schedulingShellCallLog['SchedulingShellCallLog']['current_pid'] . '...');
120:         system('kill -9 ' . $schedulingShellCallLog['SchedulingShellCallLog']['current_pid']);
121:     }
122: 
123:     private function _execInBackground($command) {
124:         if (substr(php_uname(), 0, 7) == "Windows") {
125:             return $this->_execInBackgroundWindows($command);
126:         } else {
127:             return $this->_execInBackgroundDefault($command);
128:         }
129:     }
130: 
131:     private function _execInBackgroundDefault($command) {
132:         $descriptorspec = array(
133:             0 => array("pipe", "r"), // stdin is a pipe that the child will read from
134:             1 => array("file", "/dev/null", "a"), // stdout is a pipe that the child will write to
135:             2 => array("file", "/dev/null", "a") // stderr is a file to write to
136:         );
137:         $pipes = array();
138:         $process = proc_open($command, $descriptorspec, $pipes);
139:         if ($process) {
140:             $info = proc_get_status($process);
141:             return $info['pid'];
142:         } else {
143:             throw new Exception("Process was not created");
144:         }
145:     }
146: 
147:     private function _execInBackgroundWindows($command) {
148:         throw new Exception("Not yet implemented: " . __METHOD__);
149:         //pclose(popen("start /B " . $command, "r"));
150:     }
151: 
152:     private function _shellCallCommand($schedulingShellCallLog) {
153:         return $this->_consolePath() . ' Scheduling.run_shell_call ' .
154:                 $schedulingShellCallLog['SchedulingShellCallLog']['id'];
155:     }
156: 
157:     private function _consolePath() {
158:         return APP . 'Console' . DS . 'cake';
159:     }
160: 
161:     private function _shellCallToString($shellCall) {
162:         return trim($shellCall['scheduling'] . ' ' . $shellCall['shell'] . ' ' . Scheduling::serializeArgs($shellCall['args']));
163:     }
164: 
165: }
166: 
API documentation generated by ApiGen 2.8.0