У меня есть 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); } ?>
в#!/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
Процесс зомби не обязательно плох сам по себе. Он указывает, что дочерний процесс умер, а родительский процесс еще не получил свой статус (используя wait()
или соответствующий системный вызов).
То, что происходит, выглядит следующим образом: cron
интересуется stderr от запуска скрипта (чтобы он мог отправить его по электронной почте вам, если скрипт завершился с ошибкой), поэтому он создает канал, который прикрепляет stderr скрипта к концу записи (дескриптор файла 2). Затем cron
сидит на считываемом конце трубы, ожидая выхода скрипта и чтения eof ( read()
из нулевых байтов), после чего он возвращает статус возврата сценария.
В вашем примере демона, порожденного, наследует дескриптор файла stderr , и поэтому, когда промежуточная оболочка выходит (и перестает функционировать), канал удерживается открытым демоном. Поэтому cron
никогда не читает eof и, следовательно, никогда не получает статус возврата.
Решение состоит в том, чтобы закрыть stderr вашего демона. Это может быть достигнуто следующим образом:
0-59 * * * * /var/www/html/private/fivemin/zdaemon.php >> /dev/null 2>&1 &
который будет записывать как stdout, так и stderr в /dev/null
Я думаю, что ваша главная проблема заключается в том, что stderr все еще идет в оболочку, но дочерний процесс (ваш php-процесс) спал, в результате чего происходит процесс зомби. Попробуй это:
0-59 * * * * /var/www/html/private/fivemin/zdaemon.php &> /dev/null &
Если у вас все еще возникают проблемы с зомби-процессом, взгляните на nohup .
Мне кажется странным, что я занимаюсь процессом в кронтабе. Попробуйте удалить &
в конце строки.
Обычным способом создания демона является разветвление дочернего процесса для выполнения работы, а затем выход из родительского процесса с кодом ошибки 0. Я не знаю точно, что это ваша проблема.
Я не делал этого в php, но вы могли бы использовать pcntl_fork (), чтобы имитировать обычный c-путь .