У меня были связанные проблемы один раз. Позволь мне объяснить. У меня был 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
ли PHP5.3 (или выше)? Если да, использовали ли вы 'pcntl_signal_dispatch();' поверх кода демонов или иначе объявили 'ticks'? Является ли блокировка главного демона ожиданиями детей? У некоторых детей блокировка IO? – hek2mgl
SIGKILL немного жесток; работает ли SIGTERM, когда вы запускаете его на переднем плане? –
Объявление клещей, похоже, сделало трюк. К сожалению, документация pcntl_signal не упоминает об этом в гораздо большем внимании. Объявив это, он начал работать, как ожидалось. – Shreeni