我可以使用一些帮助来了解为什么会这样.我正在从命令行运行php脚本,该脚本通过exec()启动bash脚本.在bash脚本中,我正在后台创建一个进程(例如sleep 5; echo“ Hello”&).我期望php启动bash脚本,然后在完成后继续前进.但是,php似乎正在等待bash脚本启动的后台进程完成,然后再执行其余脚本
为了演示,我将在linux shell环境中使用以下3个示例脚本:
runstuff.php
echo "PHP running stuff.sh..." . PHP_EOL;
exec('./stuff.sh &');
echo "PHP done running stuff.sh..." . PHP_EOL;
东东
#!/bin/bash
echo "stuff.sh running background process..."
# This can be a script or any process placed in the background
./test-script.sh &
echo "stuff.sh done"
测试脚本
#!/bin/bash
echo "test-script.sh waiting 5 seconds..."
sleep 5
echo "test-script.sh COMPLETE"
现在,运行php runstuff.php(从命令行)将“挂起”,直到test-script.sh完成,然后php遍历脚本的其余部分.但是,直接运行./stuff.sh将立即返回命令行提示符,并在5秒钟后显示输出.
查看运行runstuff.php时的进程列表,我可以看到test-script.sh既不是runstuff.php也不是stuff的子级,stuff.sh不再存在:
5873 pts/3 Ss 0:01 \_ bash
27389 pts/3 S+ 0:00 | \_ php runstuff.php
27390 pts/3 Z+ 0:00 | \_ [stuff.sh]
27392 pts/3 S+ 0:00 /bin/bash ./stuff.sh
27393 pts/3 S+ 0:00 \_ sleep 5
直接运行./stuff.sh时,stuff.sh看起来不错.
27963 pts/3 S 0:00 /bin/bash ./stuff.sh
27965 pts/3 S 0:00 \_ sleep 5
所以我的问题是这样的:为什么当通过php exec()执行stuff.sh时会挂起,而直接运行脚本时却没有挂起?即使它与stuff.sh分离,Php是否仍会以某种方式将test-script.sh识别为子进程?
而且,似乎将stuff.sh修改为使用&>. / dev / null&而不只是&似乎按预期工作.
修改的stuff.sh
#!/bin/bash
echo "stuff.sh running background process..."
./test-script.sh &> /dev/null &
echo "stuff.sh done"
那么,为什么将输出重定向到/ dev / null会产生预期的结果?
解决方法:
PHP exec(..)打开命令的管道,并从中读取直到关闭,然后将数据作为字符串返回(不使用).
在所有编写者都将其关闭之前,管道不会关闭,因此在以stdout打开管道的任何后台进程都会使其保持打开状态.因此,执行人员会继续等待他们,以为可能会有更多的输出.这也是一件好事:五秒钟后,它读取一条“ test-script.sh COMPLETE”消息,否则该消息将消失.
当您将stdout重定向到/ dev / null而不是后台进程时,它将不会保持管道打开,因此exec会立即返回,因为可能再也没有输出了.
标签:bash,shell,unix,linux,php
来源: https://codeday.me/bug/20191120/2042479.html