четверг, 6 февраля 2014 г.

IIS + FastCGI/PHP. Получение доступа к системному журналу событий (windows event log).

Сегодняшний мой пост будет коротким, т.к. продолжая работу на одним важным проектом, получилось так, что я не спал больше суток, и довольно специфичным. Речь пойдет о том, как из PHP скрипта под IIS получить доступ к журналу событий ОС Windows, а конкретнее, сделать в нем запись о наступившем событии. Для чего это может быть использовано? Думаю не для кого не секрет что в Windows есть такая замечательная штука, как планировщик заданий. Так вот, в последних серверный версиях ОС, есть возможность настроить выполнение какой-либо задачи в планировщике по возникновению события в системном журнале Windows.

Например, служба электропитания сообщает о том, что питание компьютера перешло в состоянии от батареи, реагируя на это событие, можно запустить скрипт, отправляющий SMS или E-Mail системному администратору. Или же, например, можно пойти дальше. Представим себе что в организации есть свой Web-сервер на базе IIS + PHP + MySQL и некий сайт / набор скриптов, выполняющийся на этом сервере. PHP скрипт может генерировать определенное событие в системном журнале Windows, которое мы можем обрабатывать в планировщике. Например, если сервер доступен извне, при запросе к скрипту http://shutdown.tld/index.php?command=1 должно осуществляться завершение работы сервера, ну или какие-то другие регламентные операции. Как это реализовать? Именно по той схеме, которую я и описал. Внутри скрипта index.php мы должны сгенерировать событие в системном журнале Windows, а в планировщике мы можем его обработать (понято, что пример приведен в образовательных целях, в реальной жизни никто не будет выключать сервер с помощью HTTP запроса, да еще и через запись событий в системный журнал). Тем неменее у меня возникла похожая задача и нужно было ее реализовать.

Сперва, давайте разберемся как сделать запись в системный журнал Windows из консоли:

eventcreate /L Application /T Information /SO "Web Control Service" /ID 1 /D "Получено внешнее событие отключения сервера."

При этом в журнале событий приложений создастся вот такое событие:


Обработку которого мы можем повесить в планировщике. Все хорошо, и казалось бы что нам мешает сделать вызов exec() или system() из php скрипта с этой же командой, чтобы получить желаемое событие в журнале. Однако - мешает. А именно то, что у пользователя IUSR от имени которого и отрабатывает PHP скрипт нет прав на запись в этот журнал. Ниже несколько крайне полезных ссылок описывающих эту проблему:

Собственно по последней я и познакомился с утилитой wevtutil с помощью которой можно задать права на чтение / запись в системный журнал для пользователя IUSR. Итак, что мы делаем:

  1. Определяем идентификатор учетной записи IURS, в моем случае им оказался S-1-5-17.
  2. Получаем текущие права на запись в журнал приложений - wevtutil gl system > C:\temp\out.txt
  3. Смотрим строку, которая начинается с channelAccess: O:BAG:SYD:(A;;0xf0007;;;SY)(A;;0x7;;;BA)(A;;0x7;;;SO)(A;;0x3;;;IU)(A;;0x3;;;SU)(A;;0x3;;;S-1-5-3)(A;;0x3;;;S-1-5-33)(A;;0x1;;;S-1-5-32-573) - это и есть текущие права.
  4. Добавляем в конец этой строки (A;;0x3;;;S-1-5-17), где 0x3 - это права на чтение и запись, а S-1-5-17 идентификатор учетки IUSR.
  5. Запускаем wevtutil sl Application /ca:O:BAG:SYD:(A;;0xf0007;;;SY)(A;;0x7;;;BA)(A;;0x7;;;SO)(A;;0x3;;;IU)(A;;0x3;;;SU)(A;;0x3;;;S-1-5-3)(A;;0x3;;;S-1-5-33)(A;;0x1;;;S-1-5-32-573)(A;;0x3;;;S-1-5-17)
После чего пользователь IUSR имеет права на запись в журнал Application и мы в PHP-скрипте можем выполнить, к примеру, такую конструкцию:

<?php
exec('eventcreate /L Application /T Information /SO "Web Control Service" /ID 1 /D "Получено внешнее событие отключения сервера."'); ?>

Профит ;)



Комментариев нет:

Отправить комментарий