diff --git a/components/process.rst b/components/process.rst index b89ac4e5f55..4500c40b633 100644 --- a/components/process.rst +++ b/components/process.rst @@ -27,7 +27,7 @@ a command in a sub-process:: use Symfony\Component\Process\Process; use Symfony\Component\Process\Exception\ProcessFailedException; - $process = new Process('ls -lsa'); + $process = new Process(array('ls', '-lsa')); $process->run(); // executes after the command finishes @@ -55,7 +55,7 @@ You can also use the :class:`Symfony\\Component\\Process\\Process` class with th foreach construct to get the output while it is generated. By default, the loop waits for new output before going to the next iteration:: - $process = new Process('ls -lsa'); + $process = new Process(array('ls', '-lsa')); $process->start(); foreach ($process as $type => $data) { @@ -72,7 +72,7 @@ for new output before going to the next iteration:: it is generated. That iterator is exposed via the ``getIterator()`` method to allow customizing its behavior:: - $process = new Process('ls -lsa'); + $process = new Process(array('ls', '-lsa')); $process->start(); $iterator = $process->getIterator($process::ITER_SKIP_ERR | $process::ITER_KEEP_OUTPUT); foreach ($iterator as $data) { @@ -90,7 +90,7 @@ with a non-zero code):: use Symfony\Component\Process\Exception\ProcessFailedException; use Symfony\Component\Process\Process; - $process = new Process('ls -lsa'); + $process = new Process(array('ls', '-lsa')); try { $process->mustRun(); @@ -100,6 +100,38 @@ with a non-zero code):: echo $exception->getMessage(); } +.. tip:: + + .. versionadded:: 3.3 + The ability to define commands as arrays of arguments was introduced in + Symfony 3.3. + + Using array of arguments is the recommended way to define commands. This + saves you from any escaping and allows sending signals seamlessly + (e.g. to stop processes before completion.):: + + $process = new Process(array('/path/command', '--flag', 'arg 1', 'etc.')); + + If you need use stream redirections, conditional execution, or any other + features provided by the shell of your operating system, you can also define + commands as strings. + + Please note that each OS provides a different syntax for their command-lines + so that it becomes your responsibility to deal with escaping and portability. + + To provide any variable arguments to command-line string, pass them as + environment variables using the second argument of the ``run()``, + ``mustRun()`` or ``start()`` methods. Referencing them is also OS-dependent:: + + // On Unix-like OSes (Linux, macOS) + $process = new Process('echo "$MESSAGE"'); + + // On Windows + $process = new Process('echo "!MESSAGE!"'); + + // On both Unix-like and Windows + $process->run(null, array('MESSAGE' => 'Something to output')); + Getting real-time Process Output -------------------------------- @@ -110,7 +142,7 @@ anonymous function to the use Symfony\Component\Process\Process; - $process = new Process('ls -lsa'); + $process = new Process(array('ls', '-lsa')); $process->run(function ($type, $buffer) { if (Process::ERR === $type) { echo 'ERR > '.$buffer; @@ -129,7 +161,7 @@ process, the :method:`Symfony\\Component\\Process\\Process::isRunning` method to check if the process is done and the :method:`Symfony\\Component\\Process\\Process::getOutput` method to get the output:: - $process = new Process('ls -lsa'); + $process = new Process(array('ls', '-lsa')); $process->start(); while ($process->isRunning()) { @@ -141,7 +173,7 @@ to check if the process is done and the You can also wait for a process to end if you started it asynchronously and are done doing other stuff:: - $process = new Process('ls -lsa'); + $process = new Process(array('ls', '-lsa')); $process->start(); // ... do other things @@ -180,7 +212,7 @@ are done doing other stuff:: a callback that is called repeatedly whilst the process is still running, passing in the output and its type:: - $process = new Process('ls -lsa'); + $process = new Process(array('ls', '-lsa')); $process->start(); $process->wait(function ($type, $buffer) { @@ -199,7 +231,7 @@ Before a process is started, you can specify its standard input using either the of the constructor. The provided input can be a string, a stream resource or a Traversable object:: - $process = new Process('cat'); + $process = new Process('cat']); $process->setInput('foobar'); $process->run(); @@ -212,7 +244,7 @@ provides the :class:`Symfony\\Component\\Process\\InputStream` class:: $input = new InputStream(); $input->write('foo'); - $process = new Process('cat'); + $process = new Process(array('cat')); $process->setInput($input); $process->start(); @@ -238,7 +270,7 @@ The input of a process can also be defined using `PHP streams`_:: $stream = fopen('php://temporary', 'w+'); - $process = new Process('cat'); + $process = new Process(array('cat')); $process->setInput($stream); $process->start(); @@ -264,7 +296,7 @@ is sent to the running process. The default signal sent to a process is ``SIGKIL Please read the :ref:`signal documentation below` to find out more about signal handling in the Process component:: - $process = new Process('ls -lsa'); + $process = new Process(array('ls', '-lsa')); $process->start(); // ... do other things @@ -285,38 +317,6 @@ instead:: ); $process->run(); -To make your code work better on all platforms, you might want to use the -:class:`Symfony\\Component\\Process\\ProcessBuilder` class instead:: - - use Symfony\Component\Process\ProcessBuilder; - - $processBuilder = new ProcessBuilder(array('ls', '-lsa')); - $processBuilder->getProcess()->run(); - -In case you are building a binary driver, you can use the -:method:`Symfony\\Component\\Process\\ProcessBuilder::setPrefix` method to prefix all -the generated process commands. - -The following example will generate two process commands for a tar binary -adapter:: - - use Symfony\Component\Process\ProcessBuilder; - - $processBuilder = new ProcessBuilder(); - $processBuilder->setPrefix('/usr/bin/tar'); - - // '/usr/bin/tar' '--list' '--file=archive.tar.gz' - echo $processBuilder - ->setArguments(array('--list', '--file=archive.tar.gz')) - ->getProcess() - ->getCommandLine(); - - // '/usr/bin/tar' '-xzf' 'archive.tar.gz' - echo $processBuilder - ->setArguments(array('-xzf', 'archive.tar.gz')) - ->getProcess() - ->getCommandLine(); - Process Timeout --------------- @@ -325,7 +325,7 @@ timeout (in seconds):: use Symfony\Component\Process\Process; - $process = new Process('ls -lsa'); + $process = new Process(array('ls', '-lsa')); $process->setTimeout(3600); $process->run(); @@ -357,7 +357,7 @@ considers the time since the last output was produced by the process:: use Symfony\Component\Process\Process; - $process = new Process('something-with-variable-runtime'); + $process = new Process(array('something-with-variable-runtime')); $process->setTimeout(3600); $process->setIdleTimeout(60); $process->run(); @@ -373,21 +373,12 @@ When running a program asynchronously, you can send it POSIX signals with the use Symfony\Component\Process\Process; - $process = new Process('find / -name "rabbit"'); + $process = new Process(array('find', '/', '-name', 'rabbit')); $process->start(); // will send a SIGKILL to the process $process->signal(SIGKILL); -.. caution:: - - Due to some limitations in PHP, if you're using signals with the Process - component, you may have to prefix your commands with `exec`_. Please read - `Symfony Issue#5759`_ and `PHP Bug#39992`_ to understand why this is happening. - - POSIX signals are not available on Windows platforms, please refer to the - `PHP documentation`_ for available signals. - Process Pid ----------- @@ -396,17 +387,11 @@ You can access the `pid`_ of a running process with the use Symfony\Component\Process\Process; - $process = new Process('/usr/bin/php worker.php'); + $process = new Process(array('/usr/bin/php', 'worker.php')); $process->start(); $pid = $process->getPid(); -.. caution:: - - Due to some limitations in PHP, if you want to get the pid of a symfony Process, - you may have to prefix your commands with `exec`_. Please read - `Symfony Issue#5759`_ to understand why this is happening. - Disabling Output ---------------- @@ -417,7 +402,7 @@ Use :method:`Symfony\\Component\\Process\\Process::disableOutput` and use Symfony\Component\Process\Process; - $process = new Process('/usr/bin/php worker.php'); + $process = new Process(array('/usr/bin/php', 'worker.php')); $process->disableOutput(); $process->run(); @@ -449,9 +434,6 @@ absolute path of the executable PHP binary available on your server:: $phpBinaryPath = $phpBinaryFinder->find(); // $phpBinaryPath = '/usr/local/bin/php' (the result will be different on your computer) -.. _`Symfony Issue#5759`: https://github.com/symfony/symfony/issues/5759 -.. _`PHP Bug#39992`: https://bugs.php.net/bug.php?id=39992 -.. _`exec`: https://en.wikipedia.org/wiki/Exec_(operating_system) .. _`pid`: https://en.wikipedia.org/wiki/Process_identifier .. _`PHP Documentation`: https://php.net/manual/en/pcntl.constants.php .. _Packagist: https://packagist.org/packages/symfony/process