Что произойдет, если работающий скрипт остановить? В случае сколь-нибудь сложной логики, последствия могут быть самыми плачевными:
Например, скрипт отправки ежедневной рассылки:
<? foreach ( $users as $user ) { send($user['email'], $subject, $html); # <- тут происходит обрыв }
# только какая-то часть пользователей получит письмо
Понятно, что если прервать этот скрипт в середине цикла, часть пользователей останутся без писем.
Если вы (либо операционная система) прерываете какой-то скрипт (процесс), то никакого “прерывания” не происходит. На самом деле, скрипту (процессу) посылается специальный сигнал “остановиться”. В ответ на этот сигнал скрипт может отправить сообщение “подождать”, тогда ОС подождет. По умолчанию, если никакого ответа от скрипта нет, он останавливается сразу.
Расширение pcntl позволяет получать и обрабатывать сигналы от операционной системы в PHP скриптах.
Простой скрипт, который перехватывает сигнал окончания работы SIGTERM:
<? # назначаем обработчик сигнала declare(ticks = 1); pcntl_signal(SIGTERM, "sig_handler"); # обработчик сигнала function sig_handler($signo) { echo "\n" . 'received signal ' . $signo . "\n"; } # бесконечный цикл while ( true ) { for ( $i = 0; $i < 3; $i++ ) { echo '.'; sleep(1); } echo "\n"; }
# Пример перехвата сигнала, посылаемого командой kill
Если запустить этот скрипт (php test.php), а в соседнем терминале попытаться его прервать командой pkill -f test.php, увидим такой вывод:
den@den:~# php test.php ... received signal 15 ... ... . received signal 15 ...
Для обработки остановки скрипта существуют такие сигналы:
В хорошем скрипте нам нужно:
1. Обработать оба этих сигнала.
2. Иметь процедуру (набор инструкций), которые обязательно нужно выполнить перед завершением.
3. Только после окончания процедуры завершения остановить выполнение скрипта.
Для этого определим обработчики и процедуру завершения:
<? declare(ticks = 1); # обработаем сигналы завершения процесса pcntl_signal(SIGTERM, "sig_handler"); pcntl_signal(SIGINT, "sig_handler"); # обработчик сигнала с процедурой завершения function sig_handler($signo) { # закончим выполнение задач echo "\n" . 'received quit signal, finishing tasks ' . "\n"; for ( $i = 0; $i < 10; $i++ ) echo '-'; echo "\n" . 'Done' . "\n"; # остановим выполнение скрипта exit; } # бесконечный цикл while ( true ) { for ( $i = 0; $i < 3; $i++ ) { echo '.'; sleep(1); } echo "\n"; }
# обработка любых сигналов об окончании работы
Теперь, если запустить скрипт и попробовать остановить его с помощью ctrl+c, увидим следующее:
den@den:~# php test.php ..^C received quit signal, finishing tasks ---------- Done
# процедура завершения всегда будет выполнена перед остановкой скрипта
Кроме остановки выполнения скрипта, существует также сигнал перезапуска SIGHUP. Его часто используют для обновления конфигурации работающих процессов без их остановки.
<? declare(ticks = 1); # объявляем настройки $date = date('Y-m-d H:i:s'); # обработаем сигналы перезапуска процесса pcntl_signal(SIGHUP, "sig_handler"); # обработчик сигнала с процедурой завершения function sig_handler($signo) { global $date; # обновляем настройки (дату) echo "\n" . 'Reloading config...' . "\n"; $date = date('Y-m-d H:i:s'); } # бесконечный цикл while ( true ) { echo $date . ': '; for ( $i = 0; $i < 3; $i++ ) { echo '.'; sleep(1); } echo "\n"; }
# обработка сигнала о перезапуске процесса
Если запустить скрипт и в соседнем терминале вызвать команду:
pkill -HUP -f test.php
Теперь вернемся к работающему скрипту и увидим следующее:
den@den:~# php test.php 2018-03-31 11:20:19: ... 2018-03-31 11:20:19: ... Reloading config... 2018-03-31 11:20:24: ... 2018-03-31 11:20:24: ...
# скрипт был перезапущен
Для процедуры перезапуска мы использовали обновление даты. Как видно, она изменилась после прихода сигнала о перезапуске. В реальных скриптах можно перезагружать файлы настроек, инициализировать заново подключения, сбрасывать кеши.
Для фоновых скриптов удобно использовать обработчики сигналов, чтобы обеспечить их правильную остановку и перезапуск. Сигналы SIGTERM и SIGNINT используются для прекращения работы скрипта, SIGHUP используется для перезапуска. В PHP обработка сигналов происходит с помощью функции pcntl_signal.
Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…
Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…
Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…
В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…
Скрипт (англ. — сценарий), — это небольшая программа, как правило, для веб-интерфейса, выполняющая определенную задачу.…
Дедлайн (от англ. deadline — «крайний срок») — это конечная дата стачи проекта или задачи…