protected function execute(InputInterface $input, OutputInterface $output) { $host = $this->getConfig('connecthost'); $port = $this->getConfig('connectport'); $timeout = $this->getConfig('connecttimeout'); $conn = $host . ':' . $port; $prompt = 'php-resque ' . $conn . '> '; $output->writeln('<comment>Connecting to ' . $conn . '...</comment>'); if (!($fh = @fsockopen('tcp://' . $host, $port, $errno, $errstr, $timeout))) { $output->writeln('<error>[' . $errno . '] ' . $errstr . ' host ' . $conn . '</error>'); return; } // Set socket timeout to 200ms stream_set_timeout($fh, 0, 200 * 1000); $stdin = fopen('php://stdin', 'r'); $prompting = false; Resque\Socket\Server::fwrite($fh, 'shell'); while (true) { if (feof($fh)) { $output->writeln('<comment>Connection to ' . $conn . ' closed.</comment>'); break; } $read = array($fh, $stdin); $write = null; $except = null; $selected = @stream_select($read, $write, $except, 0); if ($selected > 0) { foreach ($read as $r) { if ($r == $stdin) { $input = trim(fgets($stdin)); if (empty($input)) { $output->write($prompt); $prompting = true; } else { Resque\Socket\Server::fwrite($fh, $input); $prompting = false; } } elseif ($r == $fh) { $input = ''; while (($buffer = fgets($fh, 1024)) !== false) { $input .= $buffer; } if ($prompting) { $output->writeln(''); } $output->writeln('<pop>' . trim($input) . '</pop>'); if (!feof($fh)) { $output->write($prompt); $prompting = true; } } } } // Sleep for 10ms to stop CPU spiking usleep(10 * 1000); } fclose($fh); }
protected function execute(InputInterface $input, OutputInterface $output) { $cmd = $input->getArgument('cmd'); $host = $this->getConfig('connecthost'); $port = $this->getConfig('connectport'); $timeout = $this->getConfig('connecttimeout'); if (!($fh = @fsockopen('tcp://' . $host, $port, $errno, $errstr, $timeout))) { $this->log('[' . $errno . '] ' . $errstr . ' host ' . $host . ':' . $port, Resque\Logger::ERROR); return; } stream_set_timeout($fh, 0, 500 * 1000); $payload = array('cmd' => $cmd, 'id' => $input->getArgument('id'), 'force' => $input->getOption('force'), 'json' => $this->getConfig('json')); Resque\Socket\Server::fwrite($fh, json_encode($payload)); $response = ''; while (($buffer = fgets($fh, 1024)) !== false) { $response .= $buffer; } $this->log('<pop>' . trim($response) . '</pop>'); fclose($fh); }
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(); }