Есть скрипт на Bash, запускающий PHP скрипт:
#!/bin/bash
...
while [ 1 ]; do
/etc/php/bin/php "$LOADER_FILE"
done
При выполнении PHP скрипт начинает свой бесконечный цикл while(true){...}
и при выходе из этого цикла, Bash запускает PHP снова.
При нажатии Ctrl+C завершается процесс Bash и в итоге оба скрипта (Bash и PHP) завершаются.
Как реализовать на PHP такое, чтобы при нажатии на Ctrl+C завершался не процесс Bash, а процесс PHP (т.е. просто происходил рестарт PHP скрипта)?
Возможно, это реализуется с помощью readline()
(он считывает Ctrl+C и завершает скрипт), возможно это реализуется с помощью pcntl_signal()
, точно не знаю, но где-то видел, что это возможно сделать. Подскажите, пожалуйста, как?
Спасибо!
обрабатывать сигналы можно с помощью встроенной команды trap
(см. $ help trap
)
#!/bin/bash
trap 'echo "меня прервали"' int
trap 'trap - term; kill -- -$$' term
while :; do
php -r '$n=1;while(true){sleep(1);echo $n;$n++;}'
done
trap 'echo "меня прервали"' int
— «ловим» сигнал sigint (см. $ man 7 signal
), отправляемый процессу, например, при нажатии ctrl+c, и просто выводим строку "меня прервали"
. при этом сигнал отправляется и дочерним процессам (т.е., php), что в данном случае приводит к «смерти» процесса php и к следующей итерации цикла, выполняемого программой bashtrap 'trap - term; kill -- -$$' term
— «ловим» сигнал sigterm, отправляемый процессу, например, при выполнении команды $ kill идентификатор-процесса
(или $ pkill имя-процесса
).
внутри обработчика две команды:
trap - term
— отменяем перехват сигнала sigterm (иначе перехват зацикливается при выполнении следующей команды kill
и процесс завершается segfault-ом)kill -- -$$
— убиваем все процессы в группе (т.е., в том числе и выполняющийся процесс php).вообще при получении сигнала sigterm этот обработчик, конечно, срабатывает, но только если процесс bash в этот момент выполняет какую-либо свою команду. в нашем же случае в этот момент он выполняет не свою команду, а ожидает завершения процесса php, поэтому обработчик не вызывается сразу. сначала надо послать сигнал sigterm (например, командой $ kill идентификатор-процесса
), а потом — sigint (нажав ctrl+c в терминале, где выполняется скрипт).
пример вывода:
$ ./скрипт
123^Cменя прервали
123456789^CTerminated
после запуска скрипта и трёх итераций цикла while, выполняемого программой php, я нажал ctrl+c, скрипт вывел строку "меня прервали"
, и программа php была перезапущена.
после этого в соседнем окне с эмулятором терминала я послал сигнал sigterm процессу (выполнив $ pkill скрипт
), а затем нажал ctrl+c в том окне эмулятора терминала, где был запущен скрипт. за это время php «успел досчитать» до девяти.
Виртуальный выделенный сервер (VDS) становится отличным выбором
Всем привет, имеется bitrix, значения свойств инфоблока хранятся в отдельной таблицеА как посмотреть где эта отдельная таблица ??? Пару часов...
ПриветУ меня есть веб-приложение, состоящее из html-разметки и встроенного <?php ?> кода
Есть веб-сервисы внутри докер-контейнеров, назовем их api1 и api2