Что произойдет, если работающий скрипт остановить? В случае сколь-нибудь сложной логики, последствия могут быть самыми плачевными:
Например, скрипт отправки ежедневной рассылки:
<?
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.
На фоне роста спроса на ликвидность в бычьем рынке 2025 года, криптозаймы снова выходят на…
Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…
Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…
Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…
В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…
Скрипт (англ. — сценарий), — это небольшая программа, как правило, для веб-интерфейса, выполняющая определенную задачу.…