【问题标题】:Command line script run in background goes in stopped state在后台运行的命令行脚本进入停止状态
【发布时间】:2013-07-28 12:58:27
【问题描述】:

我有一个简短的 php 实用程序脚本,我只需使用以下命令从 cli 运行它:

php myscript.php

脚本始终在运行,定期执行一些任务(与问题无关)。它不需要用户的任何输入。 运行后我一般按CTRL+z然后运行bg把进程放到后台,一切正常。

如果我运行它:

php myscript.php &

脚本在启动时置于后台,但它也处于停止状态。示例:

[1] 11513
[1]+  Stopped                 php myscript.php

即使此时运行 bg 也无济于事,我必须运行 fg,然后再次运行 CTRL+zbg 才能成功工作。

这是 php 脚本:

<?
while(true){
    echo 'hi '.time()."\n";
    sleep(30);
}
?>

我的问题是我不能直接在后台运行它,因为系统停止了它,我不明白为什么。我该如何解决这个问题?

更新:

我制作了相同脚本的 bash 版本,它可以运行并放入后台(运行和不停止),只需在最后加上 & 启动它 (script.sh &amp;)

script.sh:

#!/bin/bash
while true; do
    echo `date`
    sleep 30
done

为什么 php 脚本在后台启动后停止,而 bash 脚本却没有? 什么可能导致这种不同的行为?

【问题讨论】:

  • 很高兴知道投票关闭问题的用户的原因
  • 首先,这与专业的系统管理没有明显的联系。其次,您说您的脚本任务“与问题无关”,但很明显它们是相关的并且应该被描述。
  • 为什么要明显?如果我说它不相关,它不相关:脚本只包含一个带睡眠的 while(true) :) 顺便说一句,我将它添加到我的问题中,所以它可以帮助理解它有多(不)相关。就问题而言,与它将执行什么任务无关。它直接与专业的系统管理连接,因为我在我的一台 linux 服务器中使用了这个脚本(备份目的,添加一些细节)。

标签: linux bash scripting shell php


【解决方案1】:

通常,您使用&amp; 发送到后台的进程以及等待终端输入的脚本进入停止状态。

例如有一个 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 &

并且运行良好...所以...抱歉混淆...

【讨论】:

  • 谢谢,但我不认为这可能是因为脚本不等待任何用户输入。您可以在我的问题中看到代码,它很短。另外,如果我把它放在前台然后放在后台而不插入任何输入,它就可以工作..这怎么可能?
  • @LorenzoMarcon 查看编辑 - 适合我...(只有默认的 php 安装)
  • 再次感谢,问题是在我的电脑上它也适用于我,但在服务器上却没有......我正在调查差异
  • @LorenzoMarcon - 只是一个提示:set_time_limit(0); ?
  • 我找到了导致问题的原因,并写了一个答案。既然你给了我正确的输入(readline),我会给你接受的答案:)谢谢!
【解决方案2】:

我找到了导致问题的原因。在 PHP 中,如果启用了 readline 模块,任何命令行脚本都将期待输入,即使脚本被写入为不等待用户输入。

要检查您是否启用了 readline 支持,只需运行:

php --info |grep "Readline Support"

并检查输出。如果您收到Readline Support =&gt; 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,顺便说一句..问题解决了!)

【讨论】:

  • 我也有同样的问题。我的 PHP 来自 yum,没有编译;如何禁用readline
  • 您是否尝试删除软件包 php-readline(如果已安装)?
  • php myscript.php &lt; /dev/null &amp; 为我解决了这个问题,感谢 readline 的解释
【解决方案3】:

来自http://php.net/manual/en/book.readline.php

启用 readline 后,php 会切换终端模式以接受行缓冲输入。这意味着当您通过管道传递到交互式命令时,使用 cli 的正确方法是明确指定 php 不使用终端进行输入:

php myscript.php < /dev/null &

source

【讨论】: