我有一个简短的PHP实用程序脚本,我只是用cli来运行它:
php myscript.php
脚本始终在运行,定期执行一些任务(与问题无关)。 它不需要用户的任何input。 运行后,我通常按CTRL + Z ,然后运行bg
将进程置于后台,一切正常。
如果我运行它:
php myscript.php &
脚本在启动时放在后台,但也处于停止状态。 例:
[1] 11513 [1]+ Stopped php myscript.php
即使运行bg
在这一点上没有帮助,我必须运行fg
,然后CTRL + Z和bg
再次使其工作。
这是PHP脚本:
<? while(true){ echo 'hi '.time()."\n"; sleep(30); } ?>
我的问题是,我不能直接在后台运行它,因为系统停止它,我不明白为什么。 我怎样才能解决这个问题?
更新:
我做了一个bash版本的同一个脚本,它可以运行,并放在后台(运行,而不是停止 ),只要启动它在&最后( script.sh &
)
script.sh:
#!/bin/bash while true; do echo `date` sleep 30 done
为什么php脚本在后台启动后会停止,而bash脚本不会呢? 什么可能导致这种不同的行为?
通常,这个过程是通过&
和脚本等待来自终端的输入发送到后台,进入停止状态。
例如有一个bash脚本valecho
:
#!/bin/sh read val echo $val
运行它为:
./valecho &
脚本将停止。
当运行它
echo hello | ./valecho &
将正确运行并完成。
所以,检查你的PHP – 可能要从stdin
输入的一些输入
编辑 – 基于评论:
我不是一个PHP开发人员 – 但只是尝试下一个脚本( p.php
)
<?php while(true){ echo 'hi '.time()."\n"; sleep(3); } ?>
用命令:
php -f p.php &
并且运行得很好…所以…为了混淆…
我发现是什么导致了这个问题。 在PHP中,如果启用了readline模块,任何命令行脚本都会期待输入,即使写入脚本不等待用户输入。
要检查是否启用了readline支持,只需运行:
php --info |grep "Readline Support"
并检查输出。 如果您Readline Support => enabled
readline,您可能会遇到原始问题中描述的问题。
当使用cli的正确方法是明确指定php不使用终端输入:
php myscript.php < /dev/null &
更多信息: http : //php.net/manual/en/book.readline.php
备择方案:
./test.php >/dev/null &
或(更有创意):
nohup php test.php > /dev/null 2>&1 &
(PS:我仍然相信这个问题属于serverFault,顺便说一句,问题解决了!)
从http://php.net/manual/en/book.readline.php :
当readline被启用时,php将终端模式切换为接受线路缓冲输入。 这意味着当您管道交互式命令时,使用cli的正确方法是明确指定php不使用终端进行输入:
php myscript.php < /dev/null &
资源