Сценарий командной строки, запущенный в фоновом режиме, переходит в остановленное состояние

У меня есть короткий служебный скрипт php, я запускаю его из cli просто с помощью:

php myscript.php

Скрипт работает постоянно, периодически выполняя какие-то задачи (не относящиеся к вопросу). Он не требует никакого ввода от пользователя. После запуска я обычно нажимаю 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 &)

скрипт.ш:

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

Почему php-скрипт останавливается после запуска в фоновом режиме, а bash-скрипт - нет? Что может быть причиной такого другого поведения?


person Lorenzo Marcon    schedule 28.07.2013    source источник
comment
было бы неплохо узнать причину от пользователя, который проголосовал за закрытие вопроса   -  person Lorenzo Marcon    schedule 28.07.2013
comment
Во-первых, это не имеет явной связи с профессиональным системным администрированием. Во-вторых, вы сказали, что задачи вашего сценария не имеют отношения к вопросу, но совершенно очевидно, что они имеют отношение к делу и должны были быть описаны.   -  person Michael Hampton    schedule 28.07.2013
comment
Почему это должно быть очевидно? Если я говорю, что это не имеет значения, это не имеет значения: сценарий просто содержит время (true) со сном :) Кстати, я добавил это к своему вопросу, так что это может помочь понять насколько (не)актуально. Для целей вопроса не имеет значения, какие задачи он будет выполнять. Это связано напрямую с профессиональным системным администратором, потому что я использую эти скрипты на одном из своих Linux-серверов (в целях резервного копирования, чтобы добавить некоторые детали).   -  person Lorenzo Marcon    schedule 28.07.2013


Ответы (3)


Обычно процесс, который вы отправляете в фоновый режим с &, и скрипт, ожидающий ввода с терминала, переходит в остановленное состояние.

Например. есть 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 &

и работает хорошо... так что... простите за путаницу...

person jm666    schedule 28.07.2013
comment
спасибо, но я не думаю, что это может быть так, потому что скрипт не ждет ввода данных пользователем. Вы можете увидеть код в моем вопросе, он очень короткий. Кроме того, если я поставлю его на передний план, а затем на фон без ввода каких-либо данных, он сработает ... как это может быть? - person Lorenzo Marcon; 29.07.2013
comment
@LorenzoMarcon см. редактирование - у меня работает ... (имеется только установка php по умолчанию) - person jm666; 29.07.2013
comment
еще раз спасибо, проблема в том, что на моем компьютере это работает и для меня, но на сервере это не так .. Я изучаю различия - person Lorenzo Marcon; 29.07.2013
comment
@LorenzoMarcon - только совет: set_time_limit(0);? - person jm666; 29.07.2013
comment
Я нашел причину проблемы и написал ответ. Поскольку вы дали мне правильный ответ (readline), я дам вам принятый ответ :) Спасибо! - person Lorenzo Marcon; 29.07.2013
comment
@LorenzoMarcon Спасибо - и наслаждайтесь своим сценарием. ;) - person jm666; 29.07.2013

Я нашел причину проблемы. В 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, кстати... проблема решена!)

person Lorenzo Marcon    schedule 29.07.2013
comment
У меня такая же проблема. Мой PHP от yum и не скомпилирован; как отключить readline? - person DOOManiac; 03.01.2014
comment
Вы пытались удалить пакет php-readline (если он установлен)? - person Lorenzo Marcon; 04.01.2014
comment
php myscript.php < /dev/null & решил это для меня, спасибо за объяснение readline - person Liam; 20.03.2014

Из http://php.net/manual/en/book.readline.php :

Когда readline включен, php переключает режим терминала, чтобы принимать ввод с линейной буферизацией. Это означает, что правильный способ использования cli при передаче интерактивной команды заключается в том, чтобы явно указать, что php не использует терминал для ввода:

php myscript.php < /dev/null &

источник

person Chris Montanaro    schedule 08.08.2013