"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. Там же можно установить тип запуска (Автоматический / Вручную).
Комментариев нет:
Отправить комментарий