我相信该行的其余部分是假设转储任何响应,以便 php 脚本可以继续运行
如果你不明白,这里是解释。如果你有:
exec($this->path.' start > /dev/null 2>&1 &');
> /dev/null 部分表示将 stdout(即命令产生的常规输出)重定向到 /dev/null(即空设备)。因此,命令本身产生的任何输出都将被抑制。
2>&1 部分表示将 stderror(即执行命令产生的任何错误)重定向到 stdout。然而,由于标准输出被重定向到 /dev/null,任何错误也将被重定向到那里。因此,使用这两个,它会抑制该命令将产生的任何消息。
最后,最后的&(和号)将命令分叉到一个新进程。来自Bash man page:
如果一个命令被控制操作符 & 终止,shell
在子shell 的后台执行命令。外壳可以
不等待命令完成,返回状态为 0(真)。
但是,根据this question,您正在做的事情应该有效。必须有其他事情发生以阻止进程成功分叉。只是为了排除 PHP 的问题,我首先尝试通过命令行而不是通过 PHP 的 exec 执行命令。如果还是不行,我猜是因为你的Job Control有问题。要么它以某种方式被禁用。我没有在 PHP 中尝试过,但您可以使用 set -m 命令(启用作业控制)启用它。请注意,要禁用作业控制而不是 set -m,请执行 set +m。以下是您可以在 PHP 中执行此操作的方法:
exec('set -m && ' . $this->path.' start > /dev/null 2>&1 &');
您可以做的另一件事是在 PHP 脚本执行时,登录到命令行并输入命令 jobs 并查看其输出。如果它是空白的,PHP 没有正确分叉作业。您应该会看到如下内容:
[1]+ Stopped your_command.sh
注意这里是如何写的stopped。如果进程仍在运行,这可能不应该是 stopped。
您可以做的另一件事是查看checkjobs 是启用还是禁用。登录服务器,执行以下获取内置的shell optional behavior:
shopt -p | grep checkjobs
如果输出是shopt -u checkjobs,这不是问题。如果它改为显示shopt -s checkjobs,这可能会导致您看到的行为,因为杀死带有后台作业的 shell 将导致错误说有作业正在运行并且您实际上必须杀死 shell 两次摆脱它。也许这是 PHP 开发人员没有考虑到的。在这种情况下,请在 PHP 中的命令之前添加 shopt -u checkjobs &&。
exec('shopt -u checkjobs && ' . $this->path.' start > /dev/null 2>&1 &');