Безумное поведение.продолжает делать несуществующие процессы Bash - PullRequest
1 голос
/ 20 сентября 2010

У меня есть crontab, который выглядит следующим образом:

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

0-59 * * * * /var/www/html/private/fivemin/zdaemon.php >> /dev/null &

Как можно проще, верно?

zdaemon.php, с которым я только что тестировал:

#!/usr/bin/php
<?


while(true){
        sleep(1);
}

?>

Всякий раз, когда он работает, он висит как:

root     15532  0.0  0.1 57228 1076 ?        Ss   19:09   0:00 crond
root     16681  0.0  0.1 72196 1428 ?        S    21:46   0:00 crond
root     16682  0.0  0.0     0    0 ?        Zs   21:46   0:00 [bash] <defunct>
root     16683  0.0  0.5 54800 5740 ?        S    21:46   0:00 /usr/bin/php /var/www/html/private/fivemin/zdaemon.php
root     16687  0.0  0.1 72196 1428 ?        S    21:47   0:00 crond
root     16688  0.0  0.0     0    0 ?        Zs   21:47   0:00 [bash] <defunct>
root     16689  0.0  0.5 54800 5740 ?        S    21:47   0:00 /usr/bin/php /var/www/html/private/fivemin/zdaemon.php

Я весь этот день стучал своим мозгом о стену.Кто-нибудь видел это раньше?Есть идеи?

Это ссылка на: Зависание скрипта Init.d

Ответы [ 4 ]

8 голосов
/ 20 сентября 2010

A zombie процесс не обязательно сам по себе плохой.Это означает, что процесс child умер, а процесс parent еще не получил своего статуса (используя wait() или связанный системный вызов).

Чтопроисходит следующее: cron заинтересован в stderr из сценария, который он запускает (чтобы он мог отправить его вам по электронной почте в случае сбоя сценария), поэтому он создает pipe который присоединяет stderr сценария к концу записи (дескриптор файла 2).Затем cron сидит, читая в конце канала чтения, ожидая, когда скрипт завершит работу, и прочитает eof (read() из нулевых байтов) - тогда он получит статус возврата скрипта.

В вашем примере, порожденный демон, наследует файловый дескриптор stderr , и поэтому, когда промежуточная оболочка выходит (и перестает работать), канал остается открытым демоном.Поэтому cron никогда не читает eof и, следовательно, никогда не получает статус возврата.

Решение состоит в том, чтобы гарантировать, что stderr вашего демона закрыт.Это может быть достигнуто следующим образом:

0-59 * * * * /var/www/html/private/fivemin/zdaemon.php >> /dev/null 2>&1 &

, в котором будет записано оба стандартный вывод и стандартный поток в /dev/null

2 голосов
/ 20 сентября 2010

Мне кажется странным задевать процесс в crontab.Попробуйте удалить & в конце строки.

2 голосов
/ 20 сентября 2010

Я думаю, что ваша главная проблема в том, что stderr все еще собирается в оболочку, но дочерний процесс (ваш php-процесс) спит, что приводит к процессу зомби.Попробуйте это:

0-59 * * * * /var/www/html/private/fivemin/zdaemon.php &> /dev/null &

Если у вас все еще есть проблемы с процессом зомби, взгляните на nohup .

0 голосов
/ 20 сентября 2010

Обычный способ создания демона - это разветвить дочерний процесс, чтобы выполнить работу, а затем выйти из родительского процесса с кодом ошибки 0. Однако я не уверен, что это ваша проблема.

Я не сделал этого в php, но вы могли бы использовать pcntl_fork () для имитации обычным способом c .

...