Есть скрипт на 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 «успел досчитать» до девяти.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Всем привет, имеется bitrix, значения свойств инфоблока хранятся в отдельной таблицеА как посмотреть где эта отдельная таблица ??? Пару часов...
ПриветУ меня есть веб-приложение, состоящее из html-разметки и встроенного <?php ?> кода
Есть веб-сервисы внутри докер-контейнеров, назовем их api1 и api2