Xpoint
   [напомнить пароль]

Фоновый процесс порождает "зомби" (defunct)

Метки: [без меток]
[удл]
2010-05-10 14:16:21 [обр] win_pup[досье]

Доброго времени суток!

Существует файл с php-кодом (не смотря на то, что расширение у него .inc), в котором присутствует бесконечный цикл:

while (true){
        ...
        sleep (5);
}

Задача заключается в том, чтобы сделать его фоновым процессом. Для чего был написан такой php-скрипт (db_manager.php):

#! /usr/bin/php

<?
   $pid = pcntl_fork ();
   switch ($pid){
      case 0:
         posix_setsid ();
         include_once ("inc/db_manager.inc");
         exit (0);
         break;
      case -1:
         die ("Error: unable to folk\n");
         break;
      default:
         echo "PID: ".$pid."\n";
         break;
   }
?>

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

*/3 * * * *   user   /srv/www/db_manager_watchdog.sh

, где db_manager_watchdog.sh следит за существованием фонового процесса db_manager.php и содержит следующее:

#!/bin/sh
pgrep -f db_manager.php > /dev/null
if [ $? -ne 0 ]; then
   /usr/bin/php /srv/www/db_manager.php > /dev/null
fi

Так вот, когда фоновый процесс, как обычно, отваливается, то крон вроде как выполняется, но, мало того, что фоновый процесс не работает, в системе ещё и появляется процесс db_manager_watchdog.sh как <defunct>. Видимо из-за этого оно как раз и не работает. :(

Читал на эту тему, но всё никак не могу понять, ЧТО, ГДЕ, КОГДА и КОМУ я забыл вернуть? Видимо, какой-то PID?

Буду весьма признателен за наводку.

спустя 1 час 28 минут [обр] Евгений Седов aka KPbIC(7/176)[досье]
man 1 nohup
спустя 1 час 12 минут [обр] win_pup[досье]

Типа, вставить его в manager_watchdog.sh примерно вот так:

#!/bin/sh
pgrep -f db_manager.php > /dev/null
if [ $? -ne 0 ]; then
   nohup /usr/bin/php /srv/storage1/erudit/db_manager.php > /dev/null
fi

?

спустя 38 минут [обр] Евгений Седов aka KPbIC(7/176)[досье]
nohup php.inc &
спустя 5 дней [обр] win_pup[досье]
nohup /usr/bin/php /srv/www/inc/db_manager.inc &

Таким образом процесс db_manager.inc в системе работает, чего и требовалось, но помимо этого в памяти остаются висеть ещё 2 процесса: /bin/sh /srv/www/db_manager_watchdog.sh [1] и /usr/bin/php /srv/www/db_manager.php [2], как додчерний от [1]. Убиваю [2]:

kill <pid>

, где <pid> - PID процесса [2].
В результате этого в системе вновь появляется "зомби" - [db_manager_watc] <defunct>.

спустя 12 часов [обр] Евгений Седов aka KPbIC(7/176)[досье]
Не понимаю, зачем вам нужен fork().
спустя 10 часов [обр] win_pup[досье]

Так fork() я уже не использую. В db_manager.php у меня идёт вызов:

$ret = shell_exec ("nohup /usr/bin/php /srv/storage1/erudit/inc/db_manager.inc &");

А fork() был нужен для того, что б разделить процесс на фоновый и основной, который должен выгружаться из памяти.

спустя 54 минуты [обр] Евгений Седов aka KPbIC(7/176)[досье]
У вас есть PHP-скрипт с бесконечным циклом. Соединились по SSH, вызывали этот скрипт как я писал, закрыли клиент, весь остальной обвес выкинули. Что еще нужно?
спустя 7 часов [обр] win_pup[досье]
Так я ж говорю, процесс этот, с бесконечным циклом, он иногда отваливается. Поэтому я создал watchdog, который следит за наличием процесса в системе. Watchdog выполняется кроном каждые 3 минуты. Если процесса нет - то watchdog его пытается запустить. И вот тут-то, вроде как, и рождается "зомби".
спустя 25 минут [обр] Алексей Севрюков(162/1280)[досье]
Вы бы для начала сделали так, как Вам говорят. А вот если не получится - то не watchdog надо писать, а разбираться что же этот процесс убивает.
У меня подобный скрипт работает месяцами.
спустя 15 часов [обр] win_pup[досье]

Алексей Севрюков[досье] KPbIC посоветовал запускать inc-файл, который с бесконечным циклом, посредством nohub, что я и сделал, о результатах чего я позже описал. Единственное что не пробовал, так это выполнить nohup непосредственно из командной строки, т.к. KPbIC тогда не уконкретил, в файл эту команду вставлять надо или выполнить в реальном времени.

Сейчас выполнил nohup /usr/bin/php /srv/www/inc/db_manager.inc & в реальном времени и скрипт вроде как тикает. Но когда он отваливается, его уже нужно будет запускать кроном. А вот ПОЧЕМУ именно он отваливается, мне это тоже хотелось бы знать. :(

спустя 51 минуту [обр] Евгений Седов aka KPbIC(7/176)[досье]

win_pup[досье] nohup решает проблему закрытия управляющего терминала. Если у вас скрипт падает и вы не желаете разбираться в причинах, то просто перзапустите этот скрипт по крону без всяких nohup и fork().

P.S. shebang

спустя 27 минут [обр] Алексей Севрюков(162/1280)[досье]
win_pup[досье] Вы его запускаете на виртуальном хостинге/VPS или на выделенном сервере?
спустя 44 минуты [обр] win_pup[досье]
Алексей Севрюков[досье] Ни то ни другое, но скорее всего первое. Что именно Вас интересует?
спустя 9 минут [обр] Евгений Седов aka KPbIC(7/176)[досье]

win_pup[досье]

Алексей Севрюков[досье] интересуется, есть ли у вас рутовый пароль к серверу? Если нет у вас контроля над сервером и вы пользуетесь виртуальным хостингом, то я предполагаю, что Алексей Севрюков[досье] сообщит вам, что хостер может ограничить вам ресурсы, в том числе и время исполнения скрипта, что может являться причиной его падения.

спустя 6 минут [обр] win_pup[досье]

Нет, root'ом на этом сервере я не являюсь, но сервер админят не чужие люди, к которым я всегда могу обратиться с любым вопросом напрямую. Вот только они тоже не могут понять, почему мой скрипт вываливается.

Сделал как ты сказал. Ждём падения скрипта и поднятия его через крон.

спустя 22 минуты [обр] win_pup[досье]

В общем, не стал дожидаться, собственноручно kill'нул процесс. Крон выполнился, но в итоге в памяти повисло 3 процесса:

14505 ?        Ss     0:00      \_ /bin/sh /srv/www/db_manager_watchdog.sh
14507 ?        S      0:00          \_ /usr/bin/php /srv/www/db_manager.php
14508 ?        S      0:00              \_ /usr/bin/php /srv/www/inc/db_manager.inc

При "убийстве" 14508 убиваются и все вышестоящие. Думаю, это нормально. Осталось дождаться случая, когда процесс умрёт сам своей смертью...

спустя 3 часа 20 минут [обр] Алексей Севрюков(162/1280)[досье]

В Perl чтобы "отцепить" процесс я использую perldoc Proc::Daemon (http://cpansearch.perl.org/src/EHOOD/Proc-Daemon-0.03/Daemon.pm). Происходит это так: основной скрипт "форкает" ребенка, затем ребенок особождается от связи с родителем и становится самостоятельным процессом. После этого я перехватываю все сигналы, которые могут мне помешать и все, дело в шляпе.

Может быть и в PHP есть что-то похожее. К сожалению я плохо разбираюсь и в процессах и в PHP.

Если же он у Вас умирает, то в первую очередь надо смотреть на ограничения. Неплохо было бы навесить на все возможные убивающие сигналы (HUP, TERM, INT) обработчик, который может писать лог, чтобы попытаться понять в чем может быть проблема. Либо просто заставить скрипт игнорировать эти сигналы. Как это сделать - ищите в мане по PHP.

спустя 1 месяц 21 день [обр] win_pup[досье]

В общем, тот процесс, который в предыдущем моём сообщении был под номером 14508, и который должен постоянно работать в бесконечном цикле

while (true){
        ...
        sleep (5);
}

по какой-то причине подвисает (т.е., перестаёт делать свою работу). Но т.к. в памяти он продолжает висеть, то watchdog не создаёт новый процесс.

Как бы узнать, из-за чего валится скрипт?

спустя 8 часов [обр] Евгений Седов aka KPbIC(7/176)[досье]
win_pup[досье] Создать тему в PHP, показать проблемный код.
спустя 22 дня [обр] win_pup[досье]

В скрипте с бесконечным циклом добавил ведение log'ов. В тот момент, когда скрипт якобы перестаёт работать, на самом деле он продолжает работать, а вот все запросы к базе сопровождаются ошибкой mysql-сервера:

MySQL server has gone away

Следовательно, раз запросы к базе не проходят, то и результат работы скрипта сводится на ноль.

Пытаюсь теперь понять, по какой причине всплывает такая ошибка. Поверхностное изучение показало, что причин на это может быть несколько.

спустя 7 минут [обр] win_pup[досье]
Пишут, что чаще всего такая ошибка вылетает по тайм-ауту, но откуда ж ему взяться, если мой цикл выполняется бесконечно с периодичностью в 5 сек.?
спустя 1 час 55 минут [обр] Евгений Седов aka KPbIC(7/176)[досье]
MySQL-сервер находится на другой машине?
спустя 14 минут [обр] Евгений Седов aka KPbIC(7/176)[досье]
В любом случае, прежде чем выполнять запрос, проверьте подключение к серверу, и если его нет, попытайтесь восстановить.
спустя 3 часа 36 минут [обр] Dennis F. Latypoff aka funky_dennis(4/78)[досье]
боян. в похапе нету опции MYSQL_OPT_RECONNECT при подключении. извините, не могу сдержаться: гыгыг!))
пишите патчи в php-dev.
http://dev.mysql.com/doc/refman/5.5/en/mysql-options.html
спустя 34 секунды [обр] Dennis F. Latypoff aka funky_dennis(4/78)[досье]
В любом случае, прежде чем выполнять запрос, проверьте подключение к серверу, и если его нет, попытайтесь восстановить.
Костыль.
спустя 32 минуты [обр] Евгений Седов aka KPbIC(7/176)[досье]
Dennis F. Latypoff aka funky_dennis[досье] Да, вы правы: Отвал базы по timeout и никак
спустя 1 час 2 минуты [обр] Евгений Седов aka KPbIC(7/176)[досье]
Dennis F. Latypoff aka funky_dennis[досье] А если MySQL-сервер недоступен из-за временных проблем с сетью, то почему вы считаете костылем вручную подождать перед тем как уходить в ошибку? Ведь, MYSQL_OPT_RECONNECT предпринимает лишь одну попытку.
спустя 11 часов [обр] Алексей Севрюков(162/1280)[досье]
Пытался решить такую же проблему на Perl. Нормального решения не нашел, использую "костыли" (проверяю на наличие соединения и восстанавливаю в случае разрыва, софт так же оптимизирован на запись в БД порциями, так надежнее).
спустя 7 часов [обр] Dennis F. Latypoff aka funky_dennis(4/78)[досье]
Алексей Севрюков[досье]
И даже $dbh->{mysql_auto_reconnect} = 1; не помогает?
спустя 1 минуту [обр] Dennis F. Latypoff aka funky_dennis(4/78)[досье]
Евгений Седов aka KPbIC[досье]
Проблемы с сетью это форс мажор, не таймаут.
спустя 1 день 16 часов [обр] Алексей Севрюков(162/1280)[досье]
Dennis F. Latypoff aka funky_dennis[досье] Автоматический прозрачный "реконнектор" для DBI, эта штука не работает, совсем.
Powered by POEM™ Engine Copyright © 2002-2005