问题描述
我有几行看起来像这样的代码...
I have some lines of code that look like this...
exec($this->path.' start > /dev/null 2>&1 &');
return ['status' => 'Command executed'];
$ this-> path
是一个shell脚本,start是该shell脚本的参数,我相信该行的其余部分应该转储任何响应,以便php脚本可以继续运行.它无法正常运行,php成功启动了shell脚本(将启动游戏服务器),但是php一直挂起,直到我使用shell关闭服务器为止.当我用外壳关闭服务器时,它完成执行,并且收到命令执行"响应.我还禁用了SELinux的执行,以确保它不会造成干扰.
$this->path
is a shell script, start is an argument to the shell script and I believe the rest of the line is suppose to dump any response so the php script can continue running. It is not working like it should, php is successfully launching the shell script (which launches a game server) however php just hangs until I shut the server down using the shell. When I shut the server down with the shell it finishes executing and I receive the 'command executed' response. I've also disabled enforcement of SELinux to make sure it isn't interfering.
运行Linux-Fedora 21和内置的PHP开发服务器.
Running Linux - Fedora 21 and the built in PHP development server.
推荐答案
如果您不了解,请参阅以下说明.如果您有:
If you don't understand it, here is the explanation. If you have:
exec($this->path.' start > /dev/null 2>&1 &');
>/dev/null
部分意味着将stdout(即命令生成的常规输出)重定向到/dev/null(这是空设备).因此,命令本身产生的任何输出都将被抑制.
The > /dev/null
part means to redirect stdout (i.e. the regular output produced by the command) to /dev/null (which is the null device). Therefore any output produced by the command itself will be suppressed.
2>& 1
部分表示将标准错误(即,由命令执行产生的任何错误)重定向到标准输出.但是,由于将stdout重定向到/dev/null,因此任何错误也将被重定向到该位置.因此,使用这两种方法,它可以抑制该命令将产生的任何消息.
The 2>&1
part means redirect stderror (i.e. any errors produced by the execution of the command) to stdout. However since stdout is being redirected to /dev/null, any errors will also be redirected there. Therefore with these two, it suppresses any messages that will ever be produced by the command.
最后,最后的&
(&"号)会将命令分叉到新进程.从 Bash手册页:
Finally the &
(ampersand) at the end forks the command to a new process. From the Bash man page:
但是,根据这个问题,您在做什么.必须有其他事情在进行,以防止该过程成功分叉.为了排除PHP带来的问题,我首先尝试通过命令行而不是通过PHP的exec执行命令.如果仍然无法使用,我想可能是因为您的作业控制.要么被禁用.我没有在PHP中尝试过此方法,但是您可以使用 set -m
命令(启用作业控制)来启用它.注意,要禁用作业控制而不是 set -m
,请执行 set + m
.这是您可以在PHP中执行的操作:
However, according to this question, what you are doing should be working. There must be something else going on to prevent the process from successfully forking. Just to rule out PHP from being the problem, I would first try to execute the command by the command line instead of through PHP's exec. If it still doesn't work, I would guess it's because there is a problem with your Job Control. Either it is somehow disabled. I haven't tried this in PHP, but you might be able to enable it with the set -m
command (which enables job control). Note, to disable job control instead of set -m
you do set +m
. Here is how you could do this in PHP:
exec('set -m && ' . $this->path.' start > /dev/null 2>&1 &');
您可以做的另一件事是在执行PHP脚本时,登录到命令行并键入命令 jobs
并查看其输出.如果为空,则PHP不能正确分叉作业.您应该会看到类似
Another thing you could do is while the PHP script is executing, log in to the command line and type the command jobs
and look at its output. If it is blank, PHP is not forking the jobs correctly. You should see something like:
[1]+ Stopped your_command.sh
请注意在这里怎么说 stopped
.如果进程仍在运行,则可能不应 stopped
.
Notice how here it says stopped
. This should probably not be stopped
if the process is still running.
您可以做的另一件事是查看是否启用了 checkjobs
.登录服务器并执行以下操作以获取内置的 shell可选行为:
Another thing you could do is see if checkjobs
is enabled or disabled. Log in to the server and execute the following to get the builtin shell optional behavior:
shopt -p | grep checkjobs
如果输出为 shopt -u checkjobs
,则不是问题.如果改为显示 shopt -s checkjobs
,则可能会导致您所看到的行为,因为使用后台作业杀死Shell会导致错误,提示正在运行作业,您实际上必须杀死Shell两次即可退出.也许这是PHP开发人员没有考虑的问题.在这种情况下,请在PHP中的命令前加上 shopt -u checkjobs&
.
If the output is shopt -u checkjobs
, this is not the problem. If it instead says shopt -s checkjobs
, this could cause the behavior you are seeing because killing a shell with background jobs will result in an error saying that there are jobs running and you actually have to kill the shell twice to get out of it. Maybe this is something PHP devs did not consider. In that case, prepend shopt -u checkjobs &&
before your command in PHP.
exec('shopt -u checkjobs && ' . $this->path.' start > /dev/null 2>&1 &');
这篇关于PHP在exec()bash脚本时挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!