public static function shell($commands, array $opts = []) { //$cwd = null, array $env = null, $input = null, $timeout = 60, array $options = array() if (is_array($commands)) { $procs = []; foreach ($commands as $command) { $procs[] = static::shell($command, $opts); } return $procs; } $process = new Process($commands); $options = array_replace(['type' => 'sync', 'cwd' => null, 'env' => null, 'timeout' => 60, 'callback' => null, 'output' => true], $opts); $options['cwd'] !== null && $process->setWorkingDirectory($options['cwd']); $options['env'] !== null && $process->setEnv($options['env']); is_int($options['timeout']) && $process->setTimeout($options['timeout']); if ($options['output'] === true) { $process->enableOutput(); } else { $process->disableOutput(); } $type = $options['type']; if ($type === 'sync') { $process->run($options['callback']); } elseif ($type === 'async') { $process->start(); } return $process; }
/** * Execute the command. * * @param \Symfony\Component\Console\Input\InputInterface $input * @param \Symfony\Component\Console\Output\OutputInterface $output * @return void */ public function execute(InputInterface $input, OutputInterface $output) { $project_name = $input->getArgument('project_name'); if (!$project_name) { throw new \InvalidArgumentException("I need a Project Name."); } $project_dir = getcwd() . "/" . $project_name; if (is_dir($project_dir)) { throw new \InvalidArgumentException("{$project_name} directory already exist."); } // Clone the repository $Pclone = new Process('git clone https://github.com/gpkfr/GenericVM.git ' . $project_name, getcwd(), null, null, null); $Pclone->run(function ($type, $line) use($output) { $output->write($line); }); $output->writeln('<comment>Cloning in ' . $project_dir . ' Directory...</comment> <info>✔</info>'); //init submodule $Pinit = new Process('git submodule init', $project_dir, null, null, null); $Pinit->disableOutput(); $Pinit->run(); $output->writeln('<comment>Init submodule in ' . $project_dir . ' Directory...</comment> <info>✔</info>'); //update submodule $Pupdate = new Process('git submodule update', $project_dir, null, null, null); $Pupdate->disableOutput(); $Pupdate->run(); $output->writeln('<comment>Submodule updated ...</comment> <info>✔</info>'); if (!is_file(getcwd() . DIRECTORY_SEPARATOR . $project_name . DIRECTORY_SEPARATOR . 'config.yaml')) { copy(getcwd() . DIRECTORY_SEPARATOR . $project_name . DIRECTORY_SEPARATOR . 'config.yaml.sample', getcwd() . DIRECTORY_SEPARATOR . $project_name . DIRECTORY_SEPARATOR . 'config.yaml'); $output->writeln('<comment>Creating config.yaml file...</comment> <info>✔</info>'); $output->writeln('<comment>config.yaml file created at:</comment> ' . getcwd() . DIRECTORY_SEPARATOR . $project_name . DIRECTORY_SEPARATOR . 'config.yaml'); $output->writeln('<comment>First, you need to edit your config file then launch your vm with vagrant up...</comment>'); } }
public function testCommit() { $fs = new Filesystem(); for ($i = 1; $i < 10; ++$i) { $fs->dumpFile('commit-file-' . $i, 'test commit file'); } $process = new Process('git add commit-file-1'); $process->disableOutput(); $process->mustRun(); static::assertTrue($this->object->commit('Commit file name commit-file-1')); }
/** * @param string $commandLine * @param int|null $timeout * * @throws RuntimeException * * @return bool */ private function runCommandSilently(string $commandLine, $timeout = 60) : bool { try { $process = new Process($commandLine); $process->setTimeout($timeout); $process->disableOutput(); $process->mustRun(); } catch (Exception $exception) { throw new RuntimeException($exception->getMessage(), 0, $exception); } return $process->isSuccessful(); }
/** * Start Process Background * * @param string $cmd String Cmd * * @return bool */ public function start($cmd) { $this->init(); $process = new Process($cmd . ' >> ' . $this->log . ' 2>&1'); $process->disableOutput(); $process->start(); if ($process->isRunning()) { sleep(1); $this->pid = $this->pid($cmd); } return true; }
function it_should_not_run_command_in_dry_mode(VariableContainer $variableContainer, Process $process) { $params = array('commandTemplate' => 'echo "Hello, {{ subjectOfGreeting }}"'); $variableContainer->getVariables()->willReturn(array('subjectOfGreeting' => 'WORLD')); $process->setCommandLine('echo "Hello, WORLD"')->shouldNotBeCalled(); $process->disableOutput()->shouldNotBeCalled(); $process->run()->shouldNotBeCalled(); $process->getExitCode()->shouldNotBeCalled(); $this->setParams($params); $this->setVerbose(true); $this->setDryRun(true); $this->exec()->shouldReturn(true); $this->getResult()->shouldReturn(null); $this->getOutput()->shouldReturn('command["echo "Hello, WORLD""]'); }
public function startScheduler() { /** @var TaskManagerStatus $status */ $status = $this->app['task-manager.status']; $status->start(); $cmdLine = sprintf('%s %s %s', $this->getConf()->get(['main', 'binaries', 'php_binary']), realpath(__DIR__ . '/../../../../../bin/console'), 'task-manager:scheduler:run'); $this->getDispatcher()->addListener(KernelEvents::TERMINATE, function () use($cmdLine) { $process = new Process($cmdLine); $process->setTimeout(0); $process->disableOutput(); set_time_limit(0); ignore_user_abort(true); $process->run(); }, -1000); return $this->app->redirectPath('admin_tasks_list'); }
/** * @param $output string|false * @return bool * @throws ProcessFailedException If the process was executed but failed */ public function execute(&$output) { if (!call_user_func($this->condition)) { return false; } $process = new Process($this->cmd); // NOTE: determine if keeping the return value might be useful $process->start(); $process->wait(); if (is_bool($output) && !$output) { $process->disableOutput(); } else { $output = $process->getOutput(); } if (!$process->isSuccessful()) { throw new ProcessFailedException($process); } return true; }
/** * Creates a Process instance and returns it. * * @return Process * * @throws LogicException In case no arguments have been provided */ public function getProcess() { if (0 === count($this->prefix) && 0 === count($this->arguments)) { throw new LogicException('You must add() command arguments before calling getProcess().'); } $options = $this->options; $arguments = array_merge($this->prefix, $this->arguments); $script = implode(' ', array_map(array(__NAMESPACE__ . '\\ProcessUtils', 'escapeArgument'), $arguments)); if ($this->inheritEnv) { // include $_ENV for BC purposes $env = array_replace($_ENV, $_SERVER, $this->env); } else { $env = $this->env; } $process = new Process($script, $this->cwd, $env, $this->input, $this->timeout, $options); if ($this->outputDisabled) { $process->disableOutput(); } return $process; }
/** * Start workers, put master port, server name to run on, and options stuff. */ public function startWorkers() { // Get verbosity. $verbosity = new VerbosityString($this->output); // Get current deploy.php file. $deployPhpFile = $this->input->getOption('file'); // User input. $input = ''; // Get user arguments. foreach ($this->userDefinition->getArguments() as $argument) { $value = $this->input->getArgument($argument->getName()); if ($value) { $input .= " {$value}"; } } // Get user options. foreach ($this->userDefinition->getOptions() as $option) { $value = $this->input->getOption($option->getName()); if ($value) { $input .= " --{$option->getName()} {$value}"; } } foreach ($this->servers as $serverName => $server) { $process = new Process("php " . DEPLOYER_BIN . (null === $deployPhpFile ? "" : " --file={$deployPhpFile}") . " worker " . " --master 127.0.0.1:{$this->port}" . " --server {$serverName}" . " {$input} " . " {$verbosity}" . " &"); $process->disableOutput(); $process->start(); } }
public function run() { $connected = $this->start(); $this->debug('started'); $forks = array(); if ($connected) { try { $this->debug('connected'); $work = $this->work(); $this->debug('after init work generator'); /** * Until next job maximum 1 zombie process might be hanging, * we cleanup-up zombies when receiving next job */ foreach ($work as $taskId => $payload) { $this->debug('got some work'); $message = @unserialize($payload); $processed = true; if (!$message instanceof \BackQ\Message\Process) { $work->send($processed); @error_log('Worker does not support payload of: ' . gettype($message)); } else { try { $this->debug('job timeout=' . $message->getTimeout()); /** * Enclosure in anonymous function * * ZOMBIE WARNING * @see http://stackoverflow.com/questions/29037880/start-a-background-symfony-process-from-symfony-console * * All the methods that returns results or use results probed by proc_get_status might be wrong * @see https://github.com/symfony/symfony/issues/5759 * * @tip use PHP_BINARY for php path */ $run = function () use($message) { $this->debug('launching ' . $message->getCommandline()); $process = new \Symfony\Component\Process\Process($message->getCommandline(), $message->getCwd(), $message->getEnv(), $message->getInput(), $message->getTimeout(), $message->getOptions()); /** * no win support here */ $process->setEnhanceWindowsCompatibility(false); /** * ultimately also disables callbacks */ $process->disableOutput(); /** * Execute call * proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $this->env, $this->options); * * @throws RuntimeException When process can't be launched */ $process->start(); return $process; }; /** * Loop over previous forks and gracefully stop/close them, * doing this before pushing new fork in the pool */ if (!empty($forks)) { foreach ($forks as $f) { try { /** * here we PREVENTs ZOMBIES * isRunning itself closes the process if its ended (not running) * use `pstree` to look out for zombies */ if ($f->isRunning()) { /** * If its still running, check the timeouts */ $f->checkTimeout(); } } catch (ProcessTimedOutException $e) { } } } $forks[] = $run(); } catch (\Exception $e) { /** * Not caching exceptions, just launching processes async */ @error_log('Process worker failed to run: ' . $e->getMessage()); } $work->send(true === $processed); if (true !== $processed) { /** * Worker not reliable, quitting */ throw new \RuntimeException('Worker not reliable, failed to process task: ' . $processed); } } } } catch (\Exception $e) { @error_log('Process worker exception: ' . $e->getMessage()); } } /** * Keep the references to forks until the end of execution, * attempt to close the forks nicely, * zombies will be killed upon worker death anyway */ foreach ($forks as $f) { try { /** * isRunning itself closes the process if its ended (not running) */ if ($f->isRunning()) { /** * stop async process * @see http://symfony.com/doc/current/components/process.html */ $f->checkTimeout(); $f->stop(1, SIGINT); if ($f->isRunning()) { $f->signal(SIGKILL); } } } catch (\Exception $e) { } } $this->finish(); }
/** * Generate the process. * * @return Process */ public function generate() { $options = $this->options; $arguments = array_merge([$this->binary], (array) $this->arguments); $script = implode(' ', array_map([ProcessUtils::class, 'escapeArgument'], $arguments)); $process = new Process($this->applyForceToBackground($script), $this->workingDirectory, $this->getEnvironmentVariables(), $this->input, $this->timeout, $options); if ($this->outputDisabled) { $process->disableOutput(); } return $process; }
/** * @param $address * @param $environment */ protected function startServer() { $publicDir = $this->getApplication()->getWorkingPath() . DS . 'public'; $shellCommand = $this->getBaseCommand(); $process = new Process($shellCommand, $publicDir); if ($this->getInput()->getOption('background')) { $process->disableOutput(); $process->start(); $processId = $this->getProcessId(); $this->getApplication()->getConfig()->setOption('server', ['pid' => $processId, 'address' => $address = 'http://' . $this->getAddress()]); $this->getOutput()->writeln($this->info('Server has been started at ' . $address)); } else { while ($process instanceof Process) { if (!$process->isStarted()) { $process->start(); continue; } echo $process->getIncrementalOutput(); echo $process->getIncrementalErrorOutput(); if (!$process->isRunning() || $process->isTerminated()) { $process = false; $this->getOutput()->writeln(""); $this->getOutput()->writeln($this->info('Server has been stopped.')); } sleep(1); } } }
/** * Creates a Process instance and returns it. * * @return Process * * @throws LogicException In case no arguments have been provided */ public function getProcess() { if (0 === count($this->prefix) && 0 === count($this->arguments)) { throw new LogicException('You must add() command arguments before calling getProcess().'); } $options = $this->options; $arguments = array_merge($this->prefix, $this->arguments); $script = implode(' ', array_map(array(__NAMESPACE__ . '\\ProcessUtils', 'escapeArgument'), $arguments)); $process = new Process($script, $this->cwd, $this->env, $this->input, $this->timeout, $options); if ($this->inheritEnv) { $process->inheritEnvironmentVariables(); } if ($this->outputDisabled) { $process->disableOutput(); } return $process; }
/** * Start workers, put master port, server name to run on, and options stuff. */ public function startWorkers() { $input = ['--master' => '127.0.0.1:' . $this->port, '--server' => '']; // Get verbosity. $verbosity = new VerbosityString($this->output); // Get current deploy.php file. $deployPhpFile = $this->input->getOption('file'); // Get user arguments. foreach ($this->userDefinition->getArguments() as $argument) { $input[$argument->getName()] = $this->input->getArgument($argument->getName()); } // Get user options. foreach ($this->userDefinition->getOptions() as $option) { $input["--" . $option->getName()] = $this->input->getOption($option->getName()); } foreach ($this->servers as $serverName => $server) { $input['--server'] = $serverName; $process = new Process("php " . DEPLOYER_BIN . (null === $deployPhpFile ? "" : " --file={$deployPhpFile}") . " worker " . new ArrayInput($input) . " {$verbosity}" . " &"); $process->disableOutput(); $process->run(); } }
/** * Initializes a process if possible * * @return void */ protected function init() { if ($this->maxCount === 0 || count($this->procs) < $this->maxCount) { /** @var Process $process */ $process = $this->queue->dequeue(); $proc = new Proc($process->command(), $process->directory(), $process->environment(), $process->input(), $process->timeout()); if ($process->isOutputDisabled()) { $proc->disableOutput(); } $this->startProcess($proc, $process->stdout(), $process->stderr()); $pid = $proc->getPid(); $this->pids[$pid] = true; $this->procs[$pid] = $proc; } }