-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[FrameworkBundle] Additional helper commands to control PHP's built-in web server #11311
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
@@ -256,7 +256,7 @@ public function getProcess() | |||
$options = $this->options; | |||
|
|||
$arguments = array_merge($this->prefix, $this->arguments); | |||
$script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $arguments)); | |||
$script = $arguments[0].implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), array_slice($arguments, 1))); |
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.
please revert this change
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.
Without this change I wasn't able to prefix the PHP_BINARY
call with exec
. Do you have any idea how to handle it then?
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 To be more precise: The command that should be executed leading to a "Command not found error" actually is something like:
'exec' '/usr/bin/php' ...
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.
Either we could implement a new feature in the process builder, either you can build the command manually instead of using the ProcessBuilder, but you can not decide to unescape the first 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.
Of course, you're right. I first thought that it doesn't make sense to escape the command name. But that's obviously not always true. What do you think about adding a method like useExec
to the ProcessBuilder
class?
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.
That would be indeed a nice feature. Please open a new PR for this feature as it would be easier to review this new feature in a separate thread
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 created a pull request for this (see #11335).
Both the |
{ | ||
$address = $input->getArgument('address'); | ||
|
||
if (file_exists($this->getLockFile($address))) { |
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.
The server process could have crashed. You could check if the server sends HTTP responses.
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.
Good idea. That could be done relatively easy.
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.
The lock file is now removed if the server process terminated before.
I modified this a bit. The pull request is no longer based off #11335. Instead the script that is executed by the |
Any thoughts on this? |
} elseif ($pid > 0) { | ||
$output->writeln(sprintf( | ||
'<info>Server started successfully</info>', | ||
$pid |
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 var is unused in the string.
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.
Removed it.
I've not tried it but it looks good to me. |
@romainneutron should give you some feedback soon... |
{ | ||
list($hostname, $port) = explode(':', $address); | ||
|
||
return @fsockopen($hostname, $port, $errno, $errstr, 3000) !== 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.
3000 seconds is very long timeout, I rather suggest a short one, 1 second should be enough.
Moreover, this method should return a boolean and close the socket resource once it has been created
It would be nice to add correct exitcodes (0 on success, other codes in case of failures) |
4fbf128
to
459a97e
Compare
@romainneutron I added 1 where necessary. 0 is the default behaviour. Do you think it makes sense to return 0 explicitly? |
No need to return 0 in case the command was successful |
The lock management could/should use #10475 (but it's not yet merged) |
You can then have another look. |
{ | ||
list($hostname, $port) = explode(':', $address); | ||
$fp = @fsockopen($hostname, $port, $errno, $errstr, 1); | ||
fclose($fp); |
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.
If it failed, this call would fail. You should use instead:
if (false !== $fp = @fsockopen($hostname, $port, $errno, $errstr, 1)) {
fclose($fp);
return true;
}
return 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.
Oh yes, that's true.
bde1b5e
to
e796bac
Compare
$process->start(); | ||
$lockFile = $this->getLockFile($input->getArgument('address')); | ||
touch($lockFile); | ||
|
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.
Let's add a check: If the server could not be started, let's display an error
if (!$process->isRunning()) {
$output->writeln('<error>Unable to start the server process</error>');
unlink($lockfile);
return 1;
}
|
||
private function isServerRunning($address) | ||
{ | ||
list($hostname, $port) = explode(':', $address); |
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 would trigger an error in case the address is not in the right format (for example randomstring
would trigger an Undefined index
notice
To avoid that, you can use:
explode(':', $address) + array(8000);
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.
or better, ensure the passed argument matches a regular expression
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.
Not really, there wouldn't be any server running with this address. So, there is no lock file and isServerRunning()
would never be called (see line 48).
I addressed your other suggestions. |
return 1; | ||
} elseif ($pid > 0) { | ||
$output->writeln(sprintf( | ||
'<info>Server started successfully</info>', |
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.
$pid
argument does not seem to be used with sprintf
28afe29
to
74c993c
Compare
$pid | ||
)); | ||
} else { | ||
$process = $this->createServerProcess( |
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.
It should be good to add a call to posix_setsid()
here to avoid zombie process.
if (posix_setsid() < 0) {
return 1;
}
Thanks for the feedback. |
$output->writeln('<info>Server started successfully</info>'); | ||
} else { | ||
if (posix_setsid() < 0) { | ||
return 1; |
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.
might be nice to display a nice message in case it happens like Unable to set the child process as session leader
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.
done
I'm 👍 on this one (once my last comment would be addressed) |
$output->writeln('<error>Unable to start the server process</error>'); | ||
|
||
return 1; | ||
} elseif ($pid > 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.
just if
as the previous if
returns
8464681
to
bd58bcb
Compare
Any other opinion on this? |
👍 |
Thank you @xabbuh. |
…l PHP's built-in web server (xabbuh) This PR was merged into the 2.6-dev branch. Discussion ---------- [FrameworkBundle] Additional helper commands to control PHP's built-in web server | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #10827 | License | MIT | Doc PR | symfony/symfony-docs#4005 Basically, both the ``server:status`` and ``server:stop`` wouldn't be really reliable if you had stopped the web server by, for example, killing the process. But honestly I don't know how to platform-independently determine if a process is still running given its PID. Maybe such a way could be a good improvement for the Process component. Commits ------- b601454 new helper commands for PHP's built-in server
…mands (xabbuh) This PR was merged into the 2.6-dev branch. Discussion ---------- [FrameworkBundle] add changelog entry for web server commands | Q | A | ------------- | --- | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | | License | MIT | Doc PR | I just noticed that I forgot to add a changelog entry in #11311. Commits ------- 292088f add changelog entry for web server commands
…ilt-in web server in the background (xabbuh) This PR was merged into the master branch. Discussion ---------- [Cookbook][Web server] description for running PHP's built-in web server in the background | Q | A | ------------- | --- | Doc fix? | no | New docs? | yes (symfony/symfony#11311) | Applies to | 2.6+ | Fixed tickets | Commits ------- 3caec21 description for running PHP's built-in web server in the background
Basically, both the
server:status
andserver:stop
wouldn't be really reliable if you had stopped the web server by, for example, killing the process. But honestly I don't know how to platform-independently determine if a process is still running given its PID. Maybe such a way could be a good improvement for the Process component.