register_shutdown_function
(PHP 4, PHP 5, PHP 7, PHP 8)
register_shutdown_function — Регистрирует функцию, которая выполнится при завершении работы скрипта
Описание
Список параметров
Регистрируемая завершающая функция.
Завершающие функции выполняются как часть запроса, поэтому можно отправлять данные на вывод из них и получать доступ к буферизации вывода.
Можно передавать параметры в завершающую функцию, передав дополнительные параметры.
Возвращаемые значения
Функция не возвращает значения после выполнения.
Ошибки
Примеры
Пример #1 Пример использования register_shutdown_function()
function shutdown ()
<
// Это наша завершающая функция,
// здесь мы можем выполнить все последние операции
// перед тем как скрипт полностью завершится.
Примечания
На некоторых веб-серверах рабочая директория скрипта может измениться внутри завершающей функции, например, Apache.
Смотрите также
User Contributed Notes 44 notes
If your script exceeds the maximum execution time, and terminates thusly:
The registered shutdown functions will still be executed.
I figured it was important that this be made clear!
A lot of useful services may be delegated to this useful trigger.
It is very effective because it is executed at the end of the script but before any object destruction, so all instantiations are still alive.
Here’s a simple shutdown events manager class which allows to manage either functions or static/dynamic methods, with an indefinite number of arguments without using any reflection, availing on a internal handling through func_get_args() and call_user_func_array() specific functions:
$scheduler = new shutdownScheduler ();
?>
It is easy to guess how to extend this example in a more complex context in which user defined functions and methods should be handled according to the priority depending on specific variables.
Hope it may help somebody.
Happy coding!
This demonstrates the behaviour:
register_shutdown_function ( ‘echocwd’ );
echocwd () and exit;
?>
Outputs:
cwd: /path/to/my/site/docroot/test
cwd: /
NB: CLI scripts are unaffected, and keep their CWD as the directory the script was called from.
function test2 ()< /*. */ >
function test3 ()< /*. */ >
function test_last ()< /*. */ >
register_shutdown_function ( ‘test1’ );
register_shutdown_function ( ‘test2’ );
register_shutdown_function ( ‘test3’ );
?>
the script will call functions in correct order: test1, test2, test3, test_last
When using php-fpm, fastcgi_finish_request() should be used instead of register_shutdown_function() and exit()
For example, under nginx and php-fpm 5.3+, this will make browsers wait 10 seconds to show output:
echo «You have to wait 10 seconds to see this.
» ;
register_shutdown_function ( ‘shutdown’ );
exit;
function shutdown () <
sleep ( 10 );
echo «Because exit() doesn’t terminate php-fpm calls immediately.
» ;
>
?>
This doesn’t:
echo «You can see this from the browser immediately.
» ;
fastcgi_finish_request ();
sleep ( 10 );
echo «You can’t see this form the browser.» ;
?>
while( true ) <>
?>
The output is three lines.
I was trying to figure out how to pass parameters to the register_shutdown_function() since you cannot register a function with parameters and passing through globals is not appropriate. E.g. what I was trying to do was
Turns out, the trick is to use create_function() to create a «function» that calls the desired function with static parameters.
Before: in-process logging
Maybe it would be nice to add a parameter to the register_shutdown_function that does this automatically?
The following function register_close_function should reproduce the former php behavior of closing the connection before executing the shutdown handler, based on the code posted by sts at mail dot xubion dot hu. It does not work on any machine.
I had a problem when forking a child process and accessing the variables by using the «global» keyword in the shutdown function.
So i used another way for getting the variables to the shutdown function: I passed them by reference.
// do some stuff and change the variable values
$test = 2 ;
// now the shutdown function gets called
exit( 0 );
?>
Maybe tis helps someone. (I’m using PHP 5.2.11)
function NonClassFunction () <
>
?>
there appear to be 3 ways to set a callback function in PHP (using register_shutdown_function() as an example):
2: register_shutdown_function(array(‘CallbackClass’, ‘StaticFunction’));
The following may also prove useful:
Написание системных утилит на PHP CLI

В данной статье нам хотелось бы поделиться своим опытом работы с CLI-режимом в PHP и дать несколько рекомендаций тем, кто собирается писать скрипты на PHP, при условии, что они будут запускаться в *nix-системе (впрочем, почти всё верно и для Windows).
Рекомендации
Скорость работы
Вывод на экран
В CLI- и в веб-режиме вывод на экран значительно отличается. В веб-режиме вывод, как правило, буферизуется, у пользователя нельзя ничего спросить во время исполнения скрипта; отсутствует как класс понятие вывода в поток ошибок. В CLI-режиме, естественно, неприемлем вывод HTML, а также крайне нежелателен вывод длинных строк. В CLI echo по умолчанию вызывает flush() (подробнее можно посмотреть здесь) — это удобно тем, что можно не заботиться о вызове flush() вручную, если, к примеру, вывод перенаправляется в файл.
Использование кодов возврата
Код возврата — это число, которое равно 0 в случае успешного выполнения команды и не равно 0 в противном случае. Код возврата, равный 1, часто применяется в случае некритичных ошибок (например, если указаны неправильные аргументы командной строки), а 2 — в случае критичных системных ошибок (например, при ошибке сети или диска). Значения наподобие 127 или 255 обычно используются для каких-либо специальных случаев, которые отражаются отдельно в документации.
По умолчанию при простом завершении PHP-скрипта предполагается, что все команды отработали успешно и возвращается 0. Чтобы выйти с определенным кодом возврата, нужно явно вызвать exit(NUM), где NUM — это и есть код возврата (помним, что он равен 0 в случае успеха и имеет другое значение в случае ошибок).
«Маскировка» под встроенные команды системы
Хорошая консольная утилита должна себя вести стандартным образом и пользователи могут даже и не знать, что она на PHP. Для этого в *nix-системах предусмотрен механизм, который многим известен по запуску скриптов на Perl/Python/Ruby, но в равной степени применимый и к PHP.
Обработка аргументов командной строки
Существует соглашение о формате аргументов командной строки, которому следуют большинство встроенных системных утилит, и мы рекомендуем следовать ему и ваших скриптах.
Пишите краткую справку для своего скрипта, если он получил неверное количество аргументов.
Рекомендации для более сложного уровня
Вызов «правильного» system() для CLI
О реализации system() уже было написано здесь. Речь идет о том, что стандартный system() в PHP является не вызовом system() в С, а оберткой над popen(), соответственно, «портит» STDIN и STDOUT у вызываемого скрипта. Чтобы этого не происходило, нужно пользоваться следующей функцией:
Работа с файловой системой
К возможному удивлению, мы рекомендуем не писать свои реализации рекурсивного удаления (копирования, перемещения) файлов, а вместо этого использовать встроенные команды mv, rm, cp (под Windows — соответствующие аналоги). Такое не переносимо между Windows/*nix, но зато позволяет избежать некоторых проблем, описанных ниже.
Давайте рассмотрим простой пример реализации рекурсивного удаления директории на PHP:
Очистка в случае ошибок
Если ваш скрипт делает какие-то операции с файлами (базой данных, сокетами и пр.), то зачастую возникает необходимость корректно завершать работу программы в случае возникновения непредвиденных ошибок: это может быть запись в лог, очистка временных файлов, снятие файловых блокировок и т.д.
В веб-режиме PHP это реализуется с помощью register_shutdown_function(), которая срабатывает даже тогда, когда скрипт завершился с фатальной ошибкой (этот способ, кстати, годится для отлова почти любых ошибок, в том числе ошибок нехватки памяти). В CLI-режиме всё немного сложнее, поскольку пользователь, к примеру, может послать вашему скрипту Ctrl+C, и register_shutdown_function() при этом не сработает.
Но объясняется это просто: PHP по умолчанию вообще не обрабатывает UNIX-сигналы, поэтому получение любого сигнала немедленно вызывает завершение скрипта. Это можно исправить путем добавления declare(ticks=1), в начало файла после
Php закончить выполнение скрипта
10 проверенных способов повышения монетизации сайта
Отчет о разметке для товаров в Search Console стал более детализированным
Например есть у меня script.php там 200 строк и в 55 строке условие, если например переменная равно 0 то все, прекратить выполнение всего скрипита.
либо весь скрипт обернуть в условие.
Rock’n’rolla:
Например есть у меня script.php там 200 строк и в 55 строке условие, если например переменная равно 0 то все, прекратить выполнение всего скрипита.
У вас присваивание, а не сравнение в операторе условия.
Учите матчасть. Вопросы детские до невозможности.
Rock’n’rolla, есть такая рекомендация, чтобы избегать ошибок связанных с путанием = и ==.
Рекомендуют вначале константы писать, а потом переменные:
Когда я был пионером в РНР, мне эта рекомендация очень помогла.
и верно подмечено, надо == писать, иначе if ($count = 0) всегда будет true возвращать
Если скрипт инклюжен откуда-то, то он остановит работу на этой строке, но родительский скрипт продолжит работу.
Проблемы «долгих» скриптов PHP
Внешний таймаут
В первую очередь нужно установить подходящее значение параметра max_execution_time в конфиге PHP.
Веб-сервер может также проксировать запросы на другой веб-сервер, который и запустит PHP скрипт (не редкий пример, nginx — фронтенд, apache — бэкэнд). В этом случае на проксирующем веб-сервере необходимо также настраивать таймаут проксирования. Для apache ProxyTimeout, для nginx proxy_read_timeout.
Прерывание пользователем
Если скрипт запускается в ответ на HTTP-запрос, то пользователь может остановить выполнение запроса в своем браузере, в этом случае прекратит свою работу и PHP скрипт. Если же требуется, чтобы скрипт продолжил свою работу даже после остановки запроса, установите в TRUE параметр ignore_user_abort в конфиге PHP.
Потеря открытых соединений
В таких случаях следует в первую очередь попробовать увеличить таймаут соединения. Например, для MySQL можно выполнить запрос (спасибо Snowly)
Параллельный запуск
В таких случаях можно использовать блокировку используемых ресурсов, но эта задача всегда решается индивидуально. Либо можно просто проверять, не запущена ли другая копия этого скрипта, и либо подождать завершения его работы, либо завершить текущий запуск. Для этого можно просматривать список запущенных процессов, либо использовать блокировку запуска самого скрипта, что то вроде:
Нагрузка на веб-сервер
В случаях, когда долгие скрипты запускаются через веб-сервер, соединение клиента с этим самым веб-сервером остается открытым до тех пор, пока не отработает скрипт. Это не есть хорошо, т.к. задача веб-сервера как можно быстрее обработать запрос и отдать результат. Если же соединение остается висеть, то один из воркеров (процессов) веб-сервера на долгое время будет занят. А если одновременно будет запущено достаточно много таких скриптов, то они могут занять все (ну или почти все) свободные воркеры (для apache см. MaxClients), и веб-сервер просто не сможет обрабатывать другие запросы.
Поэтому следует при обработке запроса пользователя, запускать скрипт в фоновом режиме через php-cli, чтобы не нагружать веб-сервер, а пользователю отвечать что его запрос обрабатывается. При необходимости можно периодически проверять состояние обработки при помощи AJAX запросов.
Вот, пожалуй, и все что я могу рассказать по этой теме. Надеюсь, для кого-то будет полезным.
PHP. Выполнение скрипта на фоне или аналоги
Доброго времени суток. Задача — сформировать и отдать ответ браузеру, закрыв с ним соединение, после чего продолжить выполнение скрипта. Вроде бы след.код должен работать:
Локально работает, но на сервере (не вирт.хостинг, есть возможность править конфиги) — нет. Проблема заключается в следующем — связь с браузером не разрывается. Т.е. в приведённом примере пользователю всё так же придётся ждать 10 секунд, но ‘Text user will never see’ он не увидит. В чём загвоздка? Какие параметры в php.ini следует изменить?
P.S. local — Ubuntu 11.04, PHP 5.3.5-1ubuntu7.3; online — Debian, PHP 5.2.6-1+lenny9
По поводу записи в сокет, не совсем понял вас. Не могли бы вы пояснить? Сабжевое решение мне нравится тем, что оно наиболее простое, не требует никаких доп.усилий, сохраняется всё окружение… Но я не понимаю, почему не везде работает.
Да, register_shutdown тут тоже вариант кстати.
у вас не рвут соединение, а работают с буферизацией вывода.
По поводу сокета:
Есть скрипт а.пхп, к которому обращается браузер. Он выводит то что нужно и пишет в сокет, запуская скрипт б.пхп:
Ну а в этом б.пхп делаете что нужно.
Если вам нужно сделать асинхронную обработку, вставьте в конец страницы невидимый img, а src ему ссылку на скрипт. Страница будет загружена, пользователь доволен а обработка пойдет в фоне. Но тут нет гарантии, что пользователь не закроет браузер пока ваша обработка не кончится (картинка не «загрузится»). Можете ему прогресс бар какой аяксом показывать. (Один скрипт, на который ссылка в картинке, пилит что-то в фоне и пишет прогресс в базу, другой его пользователю по аяксу отдает). А вообще все эти серверные обработки на PHP вещь неблагодатная. Лучше всего заведите табличку, в которую пишите все что надо асинхронно выполнить, и пусть каждые 10 секунд по cron на сервере запускается тот же php (хотябы через wget специального урла) и делает все асинхронное. Последнее решение наиболее стабильное. И избавляет от необходимость держать открытым браузер.
www.php.net/manual/en/features.connection-handling.php
В комментах говорят, для того, чтобы disconnect the browser and then continue processing:
header(«Content-Length: 0»);
header(«Connection: close»);
flush();





