protected function execute(InputInterface $input, OutputInterface $output) { $workers = Resque\Worker::hostWorkers(); if (empty($workers)) { $this->log('<warn>There are no workers on this host.</warn>'); return; } $table = new Resque\Helpers\Table($this); $table->setHeaders(array('#', 'Status', 'ID', 'Running for', 'Running job', 'P', 'C', 'F', 'Interval', 'Timeout', 'Memory (Limit)')); foreach ($workers as $i => $worker) { $packet = $worker->getPacket(); $table->addRow(array($i + 1, Resque\Worker::$statusText[$packet['status']], (string) $worker, Resque\Helpers\Util::human_time_diff($packet['started']), !empty($packet['job_id']) ? $packet['job_id'] . ' for ' . Resque\Helpers\Util::human_time_diff($packet['job_started']) : '-', $packet['processed'], $packet['cancelled'], $packet['failed'], $packet['interval'], $packet['timeout'], Resque\Helpers\Util::bytes($packet['memory']) . ' (' . $packet['memory_limit'] . ' MB)')); } $this->log((string) $table); }
/** * Gets Resque config variable * * @param string $key The key to search for (optional) * @param mixed $default If key not found returns this (optional) * @return mixed */ public static function getConfig($key = null, $default = null) { if (!is_null($key)) { if (false !== Util::path(static::$config, $key, $found)) { return $found; } else { return $default; } } return static::$config; }
/** * Parses the configuration file * * @return bool */ protected function parseConfig($config, $defaults) { if (array_key_exists('config', $config)) { $configFileData = Resque::readConfigFile($config['config']); foreach ($config as $key => &$value) { // If the config value is equal to the default value set in the command then // have a look at the config file. This is so that the config options can be // over-ridden in the command line. if (isset($this->configOptionMap[$key]) and (($key === 'verbose' or $value === $defaults[$key]) and false !== Util::path($configFileData, $this->configOptionMap[$key], $found))) { switch ($key) { // Need to make sure the log handlers are in the correct format case 'log': $value = array(); foreach ((array) $found as $handler => $target) { $handler = strtolower($handler); if ($target !== true) { $handler .= ':'; if (in_array($handler, array('redis:', 'mongodb:', 'couchdb:', 'amqp:'))) { $handler .= '//'; } $handler .= $target; } $value[] = $handler; } break; default: $value = $found; break; } } } $this->config = $config; return true; } return false; }
protected function execute(InputInterface $input, OutputInterface $output) { $host = $this->getConfig('listenhost'); $port = $this->getConfig('listenport'); $retry = $this->getConfig('listenretry'); $timeout = $this->getConfig('listentimeout'); $server = new Socket\Server(array('ip' => $host, 'port' => $port), $this->logger); do { try { $server->start(); } catch (Socket\Exception $e) { if ($retry) { $server->log('<error>Socket server failure: "' . $e->getMessage() . '". Retrying in ' . $timeout . ' seconds...</error>'); sleep($timeout); continue; } throw $e; } break; } while ($retry); $command = $this; $server->onConnect(function ($server, &$client, $input) { // }); $server->onDisconnect(function ($server, &$client, $message) { $server->send($client, $message); }); $server->onReceive(function ($server, &$client, $input) use($command) { if (!($data = json_decode(trim($input), true))) { $data = trim($input); } if (is_array($data)) { $cmd = $data['cmd']; unset($data['cmd']); } else { try { $input = new StringInput($data, new InputDefinition(array(new InputArgument('cmd', InputArgument::REQUIRED), new InputArgument('id', InputArgument::OPTIONAL), new InputOption('force', 'f', InputOption::VALUE_NONE), new InputOption('json', 'j', InputOption::VALUE_NONE)))); $cmd = $input->getArgument('cmd'); $data = array('id' => $input->getArgument('id'), 'force' => $input->getOption('force'), 'json' => $input->getOption('json')); } catch (\Exception $e) { $server->send($client, 'Command error: ' . $e->getMessage()); return; } } switch (strtolower($cmd)) { case 'shell': $server->send($client, 'Connected to php-resque on ' . $server . '. To quit, type "quit"'); break; case 'workers': $workers = Worker::hostWorkers(); if (empty($workers)) { $response = array('ok' => 0, 'message' => 'There are no workers running on this host.'); $server->send($client, $data['json'] ? json_encode($response) : $response['message']); return; } if ($data['json']) { $response = array('ok' => 1, 'data' => array()); foreach ($workers as $i => $worker) { $response['data'][] = $worker->getPacket(); } $server->send($client, json_encode($response)); } else { $table = new Resque\Helpers\Table($command); $table->setHeaders(array('#', 'Status', 'ID', 'Running for', 'Running job', 'P', 'C', 'F', 'Interval', 'Timeout', 'Memory (Limit)')); foreach ($workers as $i => $worker) { $packet = $worker->getPacket(); $table->addRow(array($i + 1, Worker::$statusText[$packet['status']], (string) $worker, Util::human_time_diff($packet['started']), !empty($packet['job_id']) ? $packet['job_id'] . ' for ' . Util::human_time_diff($packet['job_started']) : '-', $packet['processed'], $packet['cancelled'], $packet['failed'], $packet['interval'], $packet['timeout'], Util::bytes($packet['memory']) . ' (' . $packet['memory_limit'] . ' MB)')); } $server->send($client, (string) $table); } break; case 'worker:start': case 'worker:restart': $response = array('ok' => 0, 'message' => 'This command is not yet supported remotely.'); $server->send($client, $data['json'] ? json_encode($response) : $response['message']); break; case 'worker:pause': case 'worker:resume': case 'worker:stop': case 'worker:cancel': $valid_id = false; $id = preg_replace('/[^a-z0-9\\*:,\\.;-]/i', '', $data['id']); if (!empty($id)) { if (false === ($worker = Resque\Worker::hostWorker($id))) { if ($data['json']) { $response = array('ok' => 0, 'message' => 'Invalid worker id.'); $server->send($client, json_encode($response)); } else { $server->send($client, "Usage:\n\t{$cmd} <worker_id>\n\n" . "Help: You must specify a valid worker id, to get a \n" . "list of workers use the \"workers\" command."); } return; } $workers = array($worker); } else { $workers = Resque\Worker::hostWorkers(); if (empty($workers)) { $response = array('ok' => 0, 'message' => 'There are no workers on this host.'); $server->send($client, $data['json'] ? json_encode($response) : $response['message']); return; } } $cmd = $data['force'] ? 'worker:term' : $cmd; $signals = array('worker:pause' => SIGUSR2, 'worker:resume' => SIGCONT, 'worker:stop' => SIGQUIT, 'worker:term' => SIGTERM, 'worker:cancel' => SIGUSR1); $messages = array('worker:pause' => 'Paused worker %s', 'worker:resume' => 'Resumed worker %s', 'worker:stop' => 'Stopped worker %s', 'worker:term' => 'Force stopped worker %s', 'worker:cancel' => 'Cancelled running job on worker %s'); $response = array('ok' => 1, 'data' => array()); foreach ($workers as $worker) { $pid = $worker->getPid(); if ($cmd == 'worker:cancel') { $packet = $worker->getPacket(); $job_pid = (int) $packet['job_pid']; if ($job_pid and posix_kill($job_pid, 0)) { $pid = $job_pid; } else { $response['data'][] = array('ok' => 0, 'message' => 'The worker ' . $worker . ' has no running job to cancel.'); continue; } } if (posix_kill($pid, $signals[$cmd])) { $response['data'][] = array('ok' => 1, 'message' => sprintf($messages[$cmd], $worker)); } else { $response['data'][] = array('ok' => 0, 'message' => 'There was an error sending the signal, please try again.'); } } $server->send($client, $data['json'] ? json_encode($response) : implode(PHP_EOL, array_map(function ($d) { return $d['message']; }, $response['data']))); break; case 'job:queue': $response = array('ok' => 0, 'message' => 'Cannot queue remotely as it makes no sense. Use command `resque job:queue <job> <args> [--queue=<queue> [--delay=<delay>]]` locally.'); $server->send($client, $data['json'] ? json_encode($response) : $response['message']); break; case 'cleanup': $host = new Host(); $cleaned_hosts = $host->cleanup(); $worker = new Worker('*'); $cleaned_workers = $worker->cleanup(); $cleaned_hosts = array_merge_recursive($cleaned_hosts, $host->cleanup()); $cleaned_jobs = Job::cleanup(); if ($data['json']) { $response = array('ok' => 1, 'data' => array_merge($cleaned_hosts, $cleaned_workers, $cleaned_jobs)); $server->send($client, json_encode($response)); } else { $output = 'Cleaned hosts: ' . json_encode($cleaned_hosts['hosts']) . PHP_EOL . 'Cleaned workers: ' . json_encode(array_merge($cleaned_hosts['workers'], $cleaned_workers)) . PHP_EOL . 'Cleaned ' . $cleaned_jobs['zombie'] . ' zombie job' . ($cleaned_jobs['zombie'] == 1 ? '' : 's') . PHP_EOL . 'Cleared ' . $cleaned_jobs['processed'] . ' processed job' . ($cleaned_jobs['processed'] == 1 ? '' : 's'); } $server->send($client, $output); break; case 'shutdown': $server->shutdown(); break; case 'quit': case 'exit': $server->disconnect($client); break; default: $response = array('ok' => 0, 'message' => 'Sorry, I don\'t know what to do with command "' . $cmd . '".'); $server->send($client, $data['json'] ? json_encode($response) : $response['message']); break; } }); $server->run(); }