-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Process] add a method to the ProcessBuilder to automatically prepend the executed script with "exec" #11335
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@@ -258,6 +283,10 @@ public function getProcess() | |||
$arguments = array_merge($this->prefix, $this->arguments); | |||
$script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $arguments)); | |||
|
|||
if ($this->useExec) { | |||
$script = 'exec '.$script; | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prepending with exec will break several cases, which are not prevented by your current patch:
- Windows (which does not have
exec
) - complex commands (using
&&
,||
or multiple commands separated by;
) - enhanced sigchild compatibility mode (because of the previous case)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Does Windows have a similar command?
- How would you use
exec
in the context of multiple commands? Is that actually possible at all?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you cannot use exec
for multiple commands.
But actually, I'm not sure the ProcessBuilder allows building such commands though. It needs to be checked.
the case of sigchild is an issue though.
I don't know about such a command for windows. @romainneutron do you have an idea ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I see, the ProcessBuilder
cannot create multiple commands. Running something like this:
$builder = new ProcessBuilder(array(
'php',
'./test1.php',
';',
'php',
'./test2.php',
));
passes ;
, php
and ./test2.php
as arguments to the test1.php
script.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@romainneutron Do you have any thoughts about this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ProcessBuilder cannot create chained commands (commands separated by ;
or &&
), it only allows single commands.
I don't know any equivalent on windows, but I don't think it's relevant on this platform: We would use exec
to solve the issue mentioned in #5759 (The sh wrapper paragraph)
I think we could allow preprending on linux system that are not in sigchild environment. I've to admit this is a hacky way to solve this PHP issue, however it works very well and would allow using the ProcessBuilder when the use of exec
is needed: There is no way to use this functionality at the moment: as the ProcessBuilder escapes all arguments and as exec
is not a command (it must not be escaped), the only way is to build the command by hand, which is not something I would recommend.
I'd be in favor of such addition, with all the care and love suggested by @stof (windows and sigchild environments detection to avoid errors)
90b75f3
to
b30a57a
Compare
@stof @romainneutron Sorry for the delay. I finally changed the pull request according to your comments. However, to be able to detect sigchild environments I had to copy the detection code from the I didn't like the names |
On Linux, processes built and executed with the Process component are automatically wrapped by PHP inside a call to `sh`. This makes it hard to use methods like `getPid()` or `stop()` since they work with the `sh` process but not with the process the user intended to start. The solution is to prepend the command being executed with [exec](https://en.wikipedia.org/wiki/Exec_%28operating_system%29) (as described in symfony#5759). The `ProcessBuilder` now has two methods `enableShellWrapper()` and `disableShellWrapper()` to enable or disable the shell wrapper.
b30a57a
to
130608f
Compare
ping |
@romainneutron What's your thoughts on this PR? |
@romainneutron Any chance to get this into 2.6? |
The idea is quite interesting, but:
@fabpot What do you think about merging this in 2.6 and deprecate it in 2.7 in favor of a better support for non-escaped prefixes/arguments in 2.7 via the Process\Command? |
I don't think that it is a good idea to merge feature if which we know that it will be deprecated in the next release. I would then rather postpone this, discuss your proposal and then decide afterwards if the solution from this pull requested is really needed at all. |
I'm also against merging this if you already plan to deprecate it |
Same as the others. Closing this PR and waiting for the feature to be available in 2.7 via the Process\Command PR. |
…ars, 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
This pull requests addresses the issue raised by @romainneutron in #5759. It eases the process of creating a
Process
whose script should be prepended byexec
.