You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feature #21474 [Process] Accept command line arrays and per-run env vars, fixing signaling and escaping (nicolas-grekas)
This PR was merged into the 3.3-dev branch.
Discussion
----------
[Process] Accept command line arrays and per-run env vars, fixing signaling and escaping
| Q | A
| ------------- | ---
| Branch? | master
| Bug fix? | no
| New feature? | yes
| BC breaks? | no
| Deprecations? | yes
| Tests pass? | yes
| Fixed tickets | #12488, #11972, #10025, #11335, #5759, #5030, #19993, #10486
| License | MIT
| Doc PR | -
I think I found a way to fix this network of issues once for all.
Of all the linked ones, only the last two are still open: the remaining were closed in dead ends.
Instead of trying to make `ProcessUtil::escapeArgument` work correctly on Windows - which is impossible as discussed in #21347 - this PR deprecates it in favor of a more powerful approach.
Depending on the use case:
- when a simple command should be run, `Process` now accepts an array of arguments (the "binary" being the first arg). Making this the responsibility of `Process` (instead of `ProcessBuilder`) gives two benefits:
- escape becomes an internal detail that doesn't leak - thus can't be misused ([see here](#21347 (comment)))
- since we know we're running a single command, we can prefix it automatically by "exec" - thus fixing a long standing issue with signaling
```php
$p = new Process(array('php', '-r', 'echo 123;'));
echo $p->getCommandLine();
// displays on Linux:
// exec 'php' '-r' 'echo 123;'
```
- when a shell expression is required, passing a string is still allowed. To make it easy and look-like sql prepared statements, env vars can be used when running the command. Since the shell is OS-specific (think Windows vs Linux) - this PR assumes no portability, so one should just use each shell's specific syntax.
From the fixtures:
```php
$env = array('FOO' => 'Foo', 'BAR' => 'Bar');
$cmd = '\\' === DIRECTORY_SEPARATOR ? 'echo !FOO! !BAR! !BAZ!' : 'echo $FOO $BAR $BAZ';
$p = new Process($cmd, null, $env);
$p->run(null, array('BAR' => 'baR', 'BAZ' => 'baZ'));
$this->assertSame('Foo baR baZ', rtrim($p->getOutput()));
$this->assertSame($env, $p->getEnv());
```
Commits
-------
330b61f [Process] Accept command line arrays and per-run env vars, fixing signaling and escaping
Copy file name to clipboardExpand all lines: UPGRADE-3.3.md
+2Lines changed: 2 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -66,6 +66,8 @@ HttpKernel
66
66
Process
67
67
-------
68
68
69
+
* The `ProcessUtils::escapeArgument()` method has been deprecated, use a command line array or give env vars to the `Process::start/run()` method instead.
70
+
69
71
* Not inheriting environment variables is deprecated.
70
72
71
73
* Configuring `proc_open()` options is deprecated.
Copy file name to clipboardExpand all lines: UPGRADE-4.0.md
+2Lines changed: 2 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -228,6 +228,8 @@ HttpKernel
228
228
Process
229
229
-------
230
230
231
+
* The `ProcessUtils::escapeArgument()` method has been removed, use a command line array or give env vars to the `Process::start/run()` method instead.
232
+
231
233
* Environment variables are always inherited in sub-processes.
232
234
233
235
* Configuring `proc_open()` options has been removed.
Copy file name to clipboardExpand all lines: src/Symfony/Component/Process/PhpProcess.php
+6-9Lines changed: 6 additions & 9 deletions
Original file line number
Diff line number
Diff line change
@@ -38,20 +38,16 @@ public function __construct($script, $cwd = null, array $env = null, $timeout =
38
38
$executableFinder = newPhpExecutableFinder();
39
39
if (false === $php = $executableFinder->find()) {
40
40
$php = null;
41
+
} else {
42
+
$php = explode('', $php);
41
43
}
42
44
if ('phpdbg' === PHP_SAPI) {
43
45
$file = tempnam(sys_get_temp_dir(), 'dbg');
44
46
file_put_contents($file, $script);
45
47
register_shutdown_function('unlink', $file);
46
-
$php .= ''.ProcessUtils::escapeArgument($file);
48
+
$php[] = $file;
47
49
$script = null;
48
50
}
49
-
if ('\\' !== DIRECTORY_SEPARATOR && null !== $php) {
50
-
// exec is mandatory to deal with sending a signal to the process
51
-
// see https://github.com/symfony/symfony/issues/5030 about prepending
52
-
// command with exec
53
-
$php = 'exec '.$php;
54
-
}
55
51
if (null !== $options) {
56
52
@trigger_error(sprintf('The $options parameter of the %s constructor is deprecated since version 3.3 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED);
57
53
}
@@ -70,12 +66,13 @@ public function setPhpBinary($php)
@trigger_error(sprintf('The %s::start() method expects a second "$env" argument since version 3.3. It will be made mandatory in 4.0.', static::class), E_USER_DEPRECATED);
@@ -284,14 +312,8 @@ public function start(callable $callback = null)
284
312
@trigger_error(sprintf('Not inheriting environment variables is deprecated since Symfony 3.3 and will always happen in 4.0. Set "Process::inheritEnvironmentVariables()" to true instead.', __METHOD__), E_USER_DEPRECATED);
285
313
}
286
314
if ('\\' === DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) {
Copy file name to clipboardExpand all lines: src/Symfony/Component/Process/ProcessUtils.php
+4Lines changed: 4 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -35,9 +35,13 @@ private function __construct()
35
35
* @param string $argument The argument that will be escaped
36
36
*
37
37
* @return string The escaped argument
38
+
*
39
+
* @deprecated since version 3.3, to be removed in 4.0. Use a command line array or give env vars to the `Process::start/run()` method instead.
38
40
*/
39
41
publicstaticfunctionescapeArgument($argument)
40
42
{
43
+
@trigger_error('The '.__METHOD__.'() method is deprecated since version 3.3 and will be removed in 4.0. Use a command line array or give env vars to the Process::start/run() method instead.', E_USER_DEPRECATED);
44
+
41
45
//Fix for PHP bug #43784 escapeshellarg removes % from given string
42
46
//Fix for PHP bug #49446 escapeshellarg doesn't work on Windows
0 commit comments