Бесконечное выполнение PHP в Bash

392
05 августа 2017, 05:17

Есть скрипт на 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(), точно не знаю, но где-то видел, что это возможно сделать. Подскажите, пожалуйста, как?

Спасибо!

Answer 1

обрабатывать сигналы можно с помощью встроенной команды 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 и к следующей итерации цикла, выполняемого программой bash
  • trap '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 «успел досчитать» до девяти.

READ ALSO
Bitrix Значения свойств в отдельной таблице инфоблока

Bitrix Значения свойств в отдельной таблице инфоблока

Всем привет, имеется bitrix, значения свойств инфоблока хранятся в отдельной таблицеА как посмотреть где эта отдельная таблица ??? Пару часов...

317
Кэширование HTML и как его отключить

Кэширование HTML и как его отключить

ПриветУ меня есть веб-приложение, состоящее из html-разметки и встроенного <?php ?> кода

379
wordpress plugin Buy one click WooCommerce

wordpress plugin Buy one click WooCommerce

Ссылка на сам плагинhttps://ru

257
Общение между docker-container внутри php-приложений

Общение между docker-container внутри php-приложений

Есть веб-сервисы внутри докер-контейнеров, назовем их api1 и api2

410