2013-03-08 1 views
4

Мы запускаем PHP-демон, который смотрит в очередь, получает рабочие задания и порождает рабочего для его обработки. Рабочие сами приобретают замок в определенном месте, прежде чем продолжить.Выполнение PHP-процесса как демона при безопасном его удалении с фона

Мы порождаем Daemon как фоновые процессы nohup.

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

Если мы используем что-либо меньшее -9 (например, TERM или HUP), оно, похоже, не принимается ни демоном, ни рабочими процессами.

Неужели кто-нибудь решил эту проблему лучше?

(пс: КСТАТИ, В связи с другими соображениями, мы не можем быть в состоянии изменить наш язык реализации, поэтому, пожалуйста, только рассматривать решения на основе PHP)

+0

ли PHP5.3 (или выше)? Если да, использовали ли вы 'pcntl_signal_dispatch();' поверх кода демонов или иначе объявили 'ticks'? Является ли блокировка главного демона ожиданиями детей? У некоторых детей блокировка IO? – hek2mgl

+0

SIGKILL немного жесток; работает ли SIGTERM, когда вы запускаете его на переднем плане? –

+0

Объявление клещей, похоже, сделало трюк. К сожалению, документация pcntl_signal не упоминает об этом в гораздо большем внимании. Объявив это, он начал работать, как ожидалось. – Shreeni

ответ

3

У меня были связанные проблемы один раз. Позволь мне объяснить. У меня был php 'daemon', который работал как загрузчик. Он периодически обращался к каналам и загружал (laaaarge) контент из сети. Демон должен был быть остановлен в определенное время, допустим, 0500 утра, чтобы он не использовал всю ленту в дневное время. Я решил использовать cronjob отправить SIGTERM демону в 0500.

В демоном я имел следующий код:

pcntl_signal(SIGTERM, array($this, 'signal_handler')); 

где signal_handler выглядел так:

public function signal_handler($signal) { 
    // some cleanup code 
    exit(1); 
} 

К сожалению, это не работает: |

Мне потребовалось время, чтобы узнать, что происходит. Первое, что я выяснил, это то, что мне нужно вызвать метод pcntl_signal_dispatch() на init, чтобы вообще разрешить отправку сигналов. Цитата из дока (comments):

Если вы работаете в PHP как CLI и как «демон» (т.е. в цикле), эта функция должна вызываться в каждом цикле, чтобы проверить новые сигналы, ожидая диспетчеризацию ,

Хорошо, до сих пор работала. Но я быстро понял, что при определенных условиях даже это не сработает, как ожидалось. Иногда демона можно было остановить только kill -9 - как и раньше. : |

Так в чем проблема? .. Ответ: Моя программа называется wget, чтобы загрузить файлы через shell_exec. Проблема в том, что блокировка shell_exec() ожидает завершения дочернего процесса. Во время этого блокирующего ожидания обработка сигнала не выполняется, процесс может быть прекращен только с помощью SIGKILL - что сложно. Также проблема заключалась в том, что детские процессы должны были быть прекращены один за другим, поскольку они стали зомбическими процессами после убийства отца.

Моим решением было выполнить дочерний процесс с использованием proc_open() и использовать stream_select() на его выходе для неблокирующего ввода-вывода.

Теперь это работает как шарм. :) Если вам нужна дополнительная информация, не стесняйтесь оставить комментарий.


Примечание Если вы работаете с PHP < 5.3, то вы должны будете использовать `

declare(ticks=1); 

вместо pcntl_signal_dispatch(). Вы можете обратиться к документации для pcntl_signal(). Но если возможно, вы должны обновить PHP> = 5,3

+0

Моя проблема была решена только путем объявления тиков: declare (ticks = 1); – Shreeni

+0

@Shreeni Это потому, что pcntl_signal_dispatch() работает как с PHP 5.3, так и 'declare (ticks = 1)' является предлагаемым решением для PHP <5.3. , Вы используете PHP 5.2? Я действительно не верил, что – hek2mgl

0

Вы должны поймать сигнал (SIGTERM). Этого можно достичь с помощью функции pcntl_signal. Это даст вам возможность выполнить любые необходимые функции перед вызовом exit.

+0

Как упоминалось в проблеме, кажется, что SIGTERM не попадает, несмотря на то, что обработчики заданы через pcntl_signal. – Shreeni

1

Проблема была решена только путем добавления тиков:

// tick use required as of PHP 4.3.0 
declare(ticks = 1); 

Оставляя это само по себе является причиной моего кода не работать.

* (Очень жаль, что документация pcntl_signal не упоминает об этом в гораздо больше внимания, захватывая путь.) *

 Смежные вопросы

  • Нет связанных вопросов^_^