-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Add "executable" option to server:run console command #23721
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
@@ -69,6 +70,8 @@ public function __construct($documentRoot, $env, $address = null, $router = null | |||
if (!ctype_digit($this->port)) { | |||
throw new \InvalidArgumentException(sprintf('Port "%s" is not valid.', $this->port)); | |||
} | |||
|
|||
$this->executable = $executable; |
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.
I welcome any suggestions on how to validate this. Using is_executable
would only work for full paths. And this can be anything from xdebug
(from my original issue) to /usr/bin/php7_custom_build -c /custom/php.ini
.
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.
For now the command would just fail on the higher layer (in WebServer::run
)
$finder = new PhpExecutableFinder(); | ||
if (false === $executable = $finder->find()) { | ||
throw new \RuntimeException('Unable to find the PHP executable.'); | ||
} |
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.
I'd move this logic to WebServerConfig constructor now that it holds an executable.
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.
Moved
$env, | ||
$input->getArgument('addressport'), | ||
$input->getOption('router'), | ||
$input->getOption('executable') |
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.
Is in your oppinion "executable" correct name for what it holds? (e.g.: php
or php -c /path/to/ini
or /usr/bin/custom_php
). Other options I considered were "command" (although that clashes with Symfony command) or "binary" (which is usually the file itself, not the whole command).
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.
I believe executable
and binary
in this scenario are synonyms. Bash calls it command
, in my mind it makes a bit more sense (even though the command will be the whole string that the Process will run).
85061fb
to
cde9568
Compare
I added a test for WebServerConfig class. In first commit the test is added for the existing implementation. Then a change commit adds the "executable" parameter and tests that it works as expected. I still couldn't properly test whether the code works as a whole (see first message) and would very much welcome any suggestions on how to do it. |
be96c77
to
011d1db
Compare
Instead of adding an option for an edge case, I propose to be able to configure the executable via an env var. |
I was working on the very same issue, but I came with a different approach: 3.4...xurumelous:feature/cli-settings-server I did not change the |
@fabpot that makes sense. I'll try to update the code asap. @xurumelous yes, I thought about that as well. It's actually what most people use when debugging CLI apps. But it would not work for my case. If you look at #22101 - my exact use cases is xdebug wrapper for the php binary. What's great about it is that you have centralized configuration and all you need to know is that you need to call |
@tomasfejfar Yes, it makes sense. Are you making the change for the env variable? If you need help you can count on me. I really need to be able to set xdebug.remote_port per project. Right now I'm basically doing it manually, getting the command the |
This implementation should allow you to set the executable to If you could do the change for the env variable and send a PR from your fork to this branch, that would be great. I'll probably not have time for it this week. Did you manage to test your changes somehow? How did you approach it? I've coded the whole thing without ever running it because I couldn't get it to work (as noted in the first post) :( |
@fabpot what about setting the executable as a parameter and pulling it from the DI? I would prefer changing |
@tomasfejfar I believe I'll have time for this later today or tomorrow night. I tested in the vendor folder. I ran composer with I thought you have tested it, so I did not mention one issue before, I'll comment on the line I'm talking about. |
|
||
$process = new Process(array($binary, '-S', $config->getAddress(), $config->getRouter())); | ||
$process = new Process(array($executable, '-S', $config->getAddress(), $config->getRouter())); |
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.
I believe we should "explode" $executable
string. Depending on how the Process class is escaping the array, the first one will be the command name, see the example:
$ 'echo -e test'
bash: echo -e test: command not found
If you pass a whole string as the command, it will be interpreted as its name. I did not test it, but I believe it will do the same in the end.
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.
Oh, yes... definitely. Thanks.
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.
This is not as simple as it seems. Consider following executable: php -dmemory_limit=16M -dzend_extension="C:\Program Files\some_extension.dll"
. If I were to split this with spaces, it would break around the Program Files
part. And parsing CLI arguments is way over the scope of this PR IMHO. I've googled for some ready-made solutions and everything is in the ballpark of hundred lines of code.
I tried to repurpose \Symfony\Component\Console\Input\StringInput
for this, but it feels very hacky and I needed to add new public method to it.
See 50fda23
Tested with php index.php s:r --docroot web\ --executable "php -dmemory_limit=512M -dinclude_path=\"c:\Program Files\""
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.
Any suggestions welcome
a990d3c
to
8970e9f
Compare
I kept the various commits to allow easy revert if some of them are not OK. Tested on Windows:
Works as expected. All green. Ready for review. |
Can I do anything else to move this forward? |
Any update on this? |
$executable = $config->getExecutable(); | ||
|
||
// we need to separate the executable from the rest of the string as StringInput won't handle it | ||
$firstPartOfCommand = explode(' ', $executable)[0]; |
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.
What about a path with a space in it?
$executable = null; | ||
|
||
$envExecutable = getenv('SYMFONY_SERVER_EXECUTABLE'); | ||
if ($envExecutable !== false) { |
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.
should be false !== $envExecutable
$executable = $envExecutable; | ||
} | ||
|
||
if ($executable === null) { |
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.
Yoda-style as well
@@ -177,12 +177,12 @@ private function parseArgument($token) | |||
$arg = $this->definition->getArgument($c); | |||
$this->arguments[$arg->getName()] = $arg->isArray() ? array($token) : $token; | |||
|
|||
// if last argument isArray(), append token to last argument | |||
// if last argument isArray(), append token to last argument |
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.
should be reverted (fabbot false positive)
} elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) { | ||
$arg = $this->definition->getArgument($c - 1); | ||
$this->arguments[$arg->getName()][] = $token; | ||
|
||
// unexpected argument | ||
// unexpected argument |
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.
should be reverted (fabbot false positive)
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.
@tomasfejfar: the current logic is broken, because it implicitly mixes escaped and unescaped command line arguments (this previous comment hints it.) Instead, what about not allowing command line args in the new env var? That would require you to create a small shell wrapper to add them there, thus make everything else much simpler.
If you really want to push args in the env var, the logic needs to consider that:
- the env var is already shell-safe and doesn't need further escaping
- the added args need to be escaped
- the concatenated string needs to be prefixed by "exec" on Linux, to not break signalling the child process.
Escaping should be done in a similar way as done here:
https://github.com/symfony/symfony/blob/3.4/src/Symfony/Component/Process/ProcessBuilder.php#L270-L273
Oh btw, if you follow this path, what about putting that env var in PhpExecutableFinder? |
Moving to 4.1. Rebase on master might be needed, where PHP 7.1 features can be used btw. |
8970e9f
to
f14fde3
Compare
f14fde3
to
b5ff2ba
Compare
…_BINARY` env var (nicolas-grekas) This PR was merged into the 4.1-dev branch. Discussion ---------- [Process] Make `PhpExecutableFinder` look for the `PHP_BINARY` env var | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #22101 | License | MIT | Doc PR | - I think this is enough to fix the linked issue and thus replace #23721. ping @tomasfejfar FYI Commits ------- 4bd01f2 [Process] Make `PhpExecutableFinder` look for the `PHP_BINARY` env var
The PR adds the "executable" option to
server:run
command to allow running server with custom executable (as inbin\console server:run --executable="php -c /path/to/ini"
)I'm having a hard time testing this. The webserver bundle does not have any tests. I tried to add the symfony repo locally to my other project to test it, but I got:
Any pointers welcome.