Как стать автором
Обновить

Комментарии 33

Может, пригодиться: Про перехват и обработку фатальных ошибок (Fatal Error) в PHP ©dkLab

Насколько универсален данный способ проверки того, что демон уже запущен? О винде, конечно, не говорю. Нельзя ли блокировками файлов воспользоваться?
Если вы про monit, то у него есть куча разных тестов: это порты (причём поддерживается тонна протоколов), использование ресурсов, проверка пидов, проверка файлов и пр. Подробнее смотрите в мануале.

На практике мне обычно хватало раз в N минут проверить, открыт ли сетевой порт YYYY. Если нет — перезапуск демона на этом порту. Если Z попыток обломалось — емыло мне. Такой схемы хватает в большинстве случаев
Мы пользуемся такой же схемой как и Вы :-) относительно проверки демона по порту.
Можно через блокировки файлов. Это будет универсальней и кросс-платформенней, просто открывать файл c эксклюзивным локом.

<?php

$fp = fopen("/tmp/lock.txt", «w»);

if (flock($fp, LOCK_EX)) { // do an exclusive lock
//some logic here

} else {
die;
}

fclose($fp);

Использую такой код, еще не встречал случаи когда ошибка не обрабатывалась:

register_shutdown_function(«dbg_last_error»);

function dbg_last_error(){
$e=error_get_last();
if(($e[«type»] & E_COMPILE_ERROR) || ($e[«type»] & E_ERROR) ||
($e[«type»] & E_CORE_ERROR) || ($e[«type»] & E_RECOVERABLE_ERROR))
trace("[".$e[«type»]."] ".$e[«file»].":".$e[«line»]."\n".
$e[«message»]."\n", array(), «error»);}

Такое, как мне кажется ловит только runtime фаталы. А если будет фатал на этапе парсинга кода, то это не спасет
Пишите красивым кодом, пожалейте остальных разработчиков:
switch ($e['type'])
{
  case E_COMPILE_ERROR:
  case E_ERROR:
  case E_CORE_ERROR:
  case E_RECOVERABLE_ERROR:
    trace(.....);
}
А теперь посмотрите в чем разница между вашим кодом и тем что выше.
Лучшей читаемостью?
А ничего что там операторы не &&, а &?
Смотрим маны. Все константы ошибок — степени двойки. Поэтому битовое умножение тут вообще не нужно.
первым же делом проверил приведенный пример через браузер.
Строчки «Program still executing....» я так и не увидел, зато "(! ) Fatal error: Call to undefined function ololo() in /home/www/test/fatal.php on line 59" светилась во весь экран
нужно смотреть какие у вас настройки php

в частности html_errors, т.к. это рабочий вариант.
html_errors On
output_buffering 4096

какие еще нужны настроки?
могу выслать вам php.ini с моей локальной машины, под котороый работает.

пхп, кстати, 5.2.6.
у меня 5.2.10

Я думаю, что стоило описать полность при каких условиях работает сей код.
Указать каие именно настроки нужно включить/выключить в php.ini, чтобы получить желаемый результат
Как оказалось, нужно было отключить xdebug. Он меняет html фатала =)
Да, главного мы и не заметили :-)
мы все фатальные ошибки заворачиваем через эксепшены.
про статью на ©dkLab уже упоминали.

пару слов о мониторинге:
у нас свой собственный мониторинг (к сожалению про монит я узнал поздно)
есть класс скриптов, которые должны жить «вечно»

алгоритм приблизительно следующий:
— скрит запускается по крону каждую минуту.
— скрипт проверяет кол-во запущенных копий, кстати метод тот же через ps ax -u | grep $scriptName
— если копий больше чем нужно, то завершаемся

— далее идет цикл на длительный интервал напрмер час
в цикле выполняем метод run() & sleep(1)
— далее выполняем ps ax -u | grep getmypid() и вычисляем занимаемую память
— если в конце цикла кол-во памяти превысит допустимый — цикл заканчиваем (так избегаем утечки памяти)

— перезапускаем процесс используя php-forker
это позволяет нам запустить процесс не ровно в 00сек а например в 05сек (и не ждем 55 сек)

крон — для подтсраховки, хотя существует собственный мониторинг работы процессов.
Не понимаю, почему все пытаются ссылаться на статью с ©dkLab, там такой же метод как у меня описан. Логика таже.

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

system(«php tester.php ». getmypid(). " &" );

Ну и предотвращается варианты, когда эти недообработанные скрипты висят и засоряют память.

if(isset($_SERVER[«argv»][1])){
file_put_contents(«php://stderr», «kill {$_SERVER['argv'][1]}: ». var_export(posix_kill($_SERVER['argv'][1], 15), true)."\n");
}
Ссылаются потому что там, в частности, предусмотрена ошибка «нехватка памяти». Во-вторых, как просто дополнение в вашей статье.

За работу с процессами, безусловно, спасибо. Только вот это не относится к тематике статьи:)
:-)

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

Поэтому и был описан механизм как это делалось. Ну а статью назвал так, потому что просил программиста из команды ловить фатал ероры, а он мне утверждал, что этого в php сделать невозможно в принципе. Поэтому разозлился и написал код, а потом и жту статью. :-)

Ну, кстати, благодаря статье бклаб узнал, что register_shutdown_function сейчас вызывается когда фаерится фатал ерор, раньше такого не было. :-)
а в целом мне статья понравилась
в ней я узнал про monit
наверно тогда бы «Мы пошли другим путем»
Спасибо
system(«php tester.php ». getmypid(). " &" );
форкая таким образом ты рождаешь зомби.
необходимо обрабатывать SIGCHL

именно чтоб не было зомби и был придуман php-forker :)
нет, зомби не рождается. я же передаю ПИД текущего процесса (в котором произошла фатальная ошибка) во вновь созданный, и тот киляет этот старый процесс (который мог бы стать зомби)

iminyaylo@md-1:~$ ps -aux | grep php | grep index.php | grep -v grep
40449 26548 0.1 0.3 54628 7480 ttyp1 S 12:21 0:00 php index.php 26494
iminyaylo@md-1:~$ ps -aux | grep php | grep index.php | grep -v grep
40449 26548 0.1 0.3 54628 7480 ttyp1 S 12:21 0:00 php index.php 26494
iminyaylo@md-1:~$ ps -aux | grep php | grep index.php | grep -v grep
40449 26548 0.1 0.3 54628 7480 ttyp1 S 12:21 0:00 php index.php 26494
iminyaylo@md-1:~$ ps -aux | grep php | grep index.php | grep -v grep
40449 26548 0.0 0.3 54628 7480 ttyp1 S 12:21 0:00 php index.php 26494
iminyaylo@md-1:~$ ps -aux | grep php | grep index.php | grep -v grep
40449 26548 0.0 0.3 54628 7480 ttyp1 S 12:21 0:00 php index.php 26494
iminyaylo@md-1:~$ ps -aux | grep php | grep index.php | grep -v grep
40449 27468 0.5 0.3 54632 7472 ttyp1 S 12:22 0:00 php index.php 27460
iminyaylo@md-1:~$ ps -aux | grep php | grep index.php | grep -v grep
40449 27468 0.2 0.3 54632 7472 ttyp1 S 12:22 0:00 php index.php 27460
iminyaylo@md-1:~$ ps -aux | grep php | grep index.php | grep -v grep
40449 27468 0.2 0.3 54632 7472 ttyp1 S 12:22 0:00 php index.php 27460
iminyaylo@md-1:~$ ps -aux | grep php | grep index.php | grep -v grep
40449 27941 1.0 0.3 54628 7472 ttyp1 S 12:23 0:00 php index.php 27468
iminyaylo@md-1:~$ ps -aux | grep php | grep index.php | grep -v grep
40449 27941 0.2 0.3 54628 7472 ttyp1 S 12:23 0:00 php index.php 27468
iminyaylo@md-1:~$ ps -aux | grep php | grep index.php | grep -v grep
40449 27941 0.0 0.3 54628 7484 ttyp1 S 12:23 0:00 php index.php 27468
iminyaylo@md-1:~$ ps -aux | grep php | grep index.php | grep -v grep
40449 29381 0.0 0.3 54628 7468 ttyp1 S 12:24 0:00 php index.php 29375

Видишь, кол-во процессов не растет, а их PID-ы меняются. Здесь нет зомби-процессов.
если килл, то зомби не рождается.
я на тот случай, если мы не обрабатываем сигналы, то рождаются зомби.
Ну а это мой лог куда это пишется

kill 11162: true

live

before fork (pid: 11170)

kill 11170: true

live

live

before fork (pid: 11202)

kill 11202: true

live

before fork (pid: 11174)

kill 11174: true

live

before fork (pid: 11580)

kill 11580: true

live

before fork (pid: 11584)

kill 11584: true
Ну и я не создаю фактически дочерний процесс, дочерний процесс создается форком (pcntl_fork), здесь же я запускаю независимый процес, с другим адресным пространством посредством системного вызова. Так что тут не будет зомби.
PS мне сегодня тоже минусов за статью напихали
видно день такой…
да, и погода никчерту…
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории