"Win32service - это специфическое расширение для Windows, которое позволяет PHP взаимодействовать с Менеджером Контроля Сервисов (Service Control Manager) для запуска, остановки, регистрации и удаления сервисов, и даже позволяет вашему PHP скрипту работать как сервису." документация PHP.
Установка расширения Win32service
Для установки этого расширения предлагается его скомпилировать из исходников. Но в комментариях документации к разделу об установке можно найти ссылки на готовые .dll:
Готовое расширение от stealth35 у меня не заработало. DLL по второй ссылке, хоть и устаревшая (2009 года), но работает и для моих нужд вполне подошла.
Скачиваем нужную библиотеку, в моём случае это "php_win32service-svn-20091011-5.3-vc6-x86.zip", и подключаем её к PHP.
Построение скрипта
Прежде всего нужно придумать имя сервиса (для команд, без пробелов) и название для отображения в списке сервисов.
$service_name = 'win_service'; $display_name = 'Test windows service';
Создаваемый скрипт будет выполняться через комнадную строку, и будет получать один аргумент для управления.
Код управления сервисом и его полезная часть (та, что выполняет работу) в нашем случае будет находится в одном и том же файле. Наш сервис может получать следующие команды:
- install
- uninstall
- start
- stop
при выполнении этих команд передаётся сообщение указанному сервису и дальше работа скрипта прерывается. Есть ещё один аргумент:
- run
он сообщает что сервис запущен и надо что-то делать. При получении "run" скрипт начинает выполнять свою полезную часть.
define('NL', "\n\n"); define('DNL', NL . NL); if (!isset($argv[1])) { echo 'no argument' . DNL; exit; } switch ($argv[1]) { case 'install': $result = win32_create_service(array( 'service' => $service_name, 'display' => $display_name, 'params' => '-f ' . __FILE__ . ' run', 'path' => 'php', )); var_dump($result); echo 'Service Installed' . DNL; exit; case 'uninstall': $result = win32_delete_service($service_name); var_dump($result); echo 'Service Removed' . DNL; exit; case 'start': $result = win32_start_service($service_name); var_dump($result); echo 'Service Started' . DNL; exit; case 'stop': $result = win32_stop_service($service_name); var_dump($result); echo 'Service Stopped' . DNL; exit; case 'run': break; default: echo 'unknown argument' . DNL; exit(); }Описание функций, параметров и возвращаемых значений можно посмотреть в документации к PHP.
Всё что нужно сделать во второй части это
- Зарегистрироваться как сервис.
- Выполнять свой код, периодически проверяя поступившие сообщения.
- Отвечать на полученные сообщения.
set_time_limit(0); if (!win32_start_service_ctrl_dispatcher($service_name)) exit('Cannot register script as service: "' . $service_name . '"'); win32_set_service_status(WIN32_SERVICE_RUNNING); // main loop while (1) { // Handle Windows Service Request switch (win32_get_last_control_message()) { case WIN32_SERVICE_CONTROL_INTERROGATE: // Report its current status to the SCM win32_set_service_status(WIN32_NO_ERROR); break; case WIN32_SERVICE_CONTROL_STOP: // Service should stop win32_set_service_status(WIN32_SERVICE_STOPPED); break(2); default: win32_set_service_status(WIN32_ERROR_CALL_NOT_IMPLEMENTED); } // Полезный код сервиса // ... // ... } // set appropriate status win32_set_service_status(WIN32_SERVICE_STOPPED);Это весь код. Дополнительно можно обрабатывать сообщения "Пауза", "Продолжение" (снятие паузы), "Выключение" (ОС).
Установка, работа
Добавляю запись в лог для проверки работы. Результат полностью:
$service_name = 'win_service'; $display_name = 'Test windows service'; define('NL', "\n\n"); define('DNL', NL . NL); function dumpToFile($variable) { $sep = "\r\n"; $handle = fopen('d:\\Dev\\htdocs\\win_service\\log.log', 'a+'); fwrite($handle, '[' . date('H:i:s') . '] '); ob_start(); print_r($variable); $printed = ob_get_clean(); fwrite($handle, $printed . $sep); fclose($handle); } if (!isset($argv[1])) { echo 'no argument' . DNL; exit; } switch ($argv[1]) { case 'install': $result = win32_create_service(array( 'service' => $service_name, 'display' => $display_name, 'params' => '-f ' . __FILE__ . ' run', 'path' => 'php', )); var_dump($result); echo 'Service Installed' . DNL; exit; case 'uninstall': $result = win32_delete_service($service_name); var_dump($result); echo 'Service Removed' . DNL; exit; case 'start': $result = win32_start_service($service_name); var_dump($result); echo 'Service Started' . DNL; exit; case 'stop': $result = win32_stop_service($service_name); var_dump($result); echo 'Service Stopped' . DNL; exit; case 'run': break; default: echo 'unknown argument' . DNL; exit(); } set_time_limit(0); if (!win32_start_service_ctrl_dispatcher($service_name)) exit('Cannot register script as service: "' . $service_name . '"'); win32_set_service_status(WIN32_SERVICE_RUNNING); // main loop while (1) { // Handle Windows Service Request switch (win32_get_last_control_message()) { case WIN32_SERVICE_CONTROL_INTERROGATE: // Report its current status to the SCM win32_set_service_status(WIN32_NO_ERROR); break; case WIN32_SERVICE_CONTROL_STOP: // Service should stop win32_set_service_status(WIN32_SERVICE_STOPPED); break(2); default: win32_set_service_status(WIN32_ERROR_CALL_NOT_IMPLEMENTED); } // Полезный код сервиса // ... // ... dumpToFile('working'); sleep(20); } // set appropriate status win32_set_service_status(WIN32_SERVICE_STOPPED);
Команды управления сервисом выглядят так:
1. установка
php -f d:\Dev\htdocs\win_service\service.php install
2. запуск
php -f d:\Dev\htdocs\win_service\service.php start
3. остановка
php -f d:\Dev\htdocs\win_service\service.php stop
4. удаление
php -f d:\Dev\htdocs\win_service\service.php uninstall
Также нашим сервисом можно управлять через Control Panel -> Administrative Tools -> Services. Там же можно установить тип запуска (Автоматический / Вручную).
Комментариев нет:
Отправить комментарий