· 15 мин чтения

Анализ журналов Windows Event Log через PowerShell: поиск причин сбоев и аудит

Меня зовут Семёнов Евгений Сергеевич, директор АйТи Фреш. За 15+ лет эксплуатации Windows-парка я прошёл путь от щелчков мышкой в eventvwr.msc до автоматизированных XPath-фильтров, которые обрабатывают логи с полусотни серверов за 40 секунд. У нас на практике именно грамотный разбор Event Log спасает от недельных простоев: правильный запрос за минуту выдаёт то, что ручной просмотр не найдёт никогда.

Почему Event Viewer не справляется и нужен PowerShell

Стандартный eventvwr.msc — удобен для просмотра одной машины, но становится беспомощным, когда нужно свести данные с 10 серверов или найти закономерность в миллионе записей. Я всегда использую PowerShell cmdlet Get-WinEvent — он читает и классические логи (System, Application, Security), и современные каналы Applications and Services Logs, включая Microsoft-Windows-TaskScheduler, GroupPolicy, PrintService и сотни других.

Ключевое преимущество Get-WinEvent — фильтрация на стороне поставщика событий. Вы не грузите в память весь журнал, а сразу просите Windows отдать только нужные записи по каналу, уровню, идентификатору и времени. Это ускоряет работу в десятки раз.

Базовый синтаксис Get-WinEvent

Самая частая форма — FilterHashtable. Это короткий и быстрый способ отфильтровать по каналу, уровню, идентификатору и времени:

# Последние ошибки в System за сутки
Get-WinEvent -FilterHashtable @{
  LogName   = 'System'
  Level     = 2          # Error
  StartTime = (Get-Date).AddDays(-1)
} | Select-Object TimeCreated, Id, ProviderName, Message -First 20

# События старта и остановки служб
Get-WinEvent -FilterHashtable @{
  LogName = 'System'
  Id      = 7034,7036,7040
  StartTime = (Get-Date).AddHours(-4)
}

Если параметров FilterHashtable не хватает — переходите на FilterXPath. Это полноценный язык запросов, который поддерживает вложенные условия и поиск по полям EventData:

# Все успешные входы пользователя ivanov за сегодня
Get-WinEvent -LogName Security -FilterXPath @"
*[System[EventID=4624] and EventData[Data[@Name='TargetUserName']='ivanov']]
"@

Какие EventID нужно знать наизусть

У меня в блокноте висит короткий список идентификаторов, которые покрывают 80% повседневных расследований. Привожу его ниже — рекомендую распечатать:

EventIDКаналЧто значит
4624 / 4625SecurityУспешный / неуспешный вход
4740SecurityБлокировка учётки
4720 / 4726SecurityСоздание / удаление пользователя
7034 / 7036 / 7040SystemСбой службы / старт-стоп / смена типа запуска
6005 / 6006 / 6008SystemСтарт / штатная остановка / внеплановая перезагрузка
41System (Kernel-Power)Машина ушла в ребут без штатного shutdown
1000 / 1001ApplicationАварийное завершение приложения / Windows Error Reporting

Расследование причины перезагрузки сервера

Классический вопрос от клиента: «Сервер ушёл в перезагрузку ночью, что случилось?». Мой типовой запрос:

Get-WinEvent -FilterHashtable @{
  LogName = 'System'
  Id      = 41,1074,6006,6008,6005,13
  StartTime = (Get-Date).AddDays(-2)
} | Sort-Object TimeCreated | Format-Table TimeCreated, Id, ProviderName, Message -AutoSize -Wrap

Интерпретация короткая. 1074 — кто-то отправил shutdown через команду или GPO. 6006+6005 подряд — штатный reboot. 41 без 1074 — BSOD, скачок питания или жёсткий ребут по кнопке. 6008 без 6006 — аварийное выключение.

Сбор логов с парка серверов

Когда серверов больше пяти, я разворачиваю либо Windows Event Forwarding (WEF) с централизованным коллектором, либо на скорую руку собираю данные через Invoke-Command. Второй вариант годится для разовой диагностики:

$servers = 'DC01','DC02','FS01','EX01','SQL01'

$results = Invoke-Command -ComputerName $servers -ScriptBlock {
  Get-WinEvent -FilterHashtable @{
    LogName='System'; Level=1,2; StartTime=(Get-Date).AddHours(-6)
  } | Select TimeCreated, Id, ProviderName, Message
}

$results | Sort PSComputerName, TimeCreated |
  Export-Csv -Path "C:\Reports\errors-$(Get-Date -Format yyyyMMdd-HHmm).csv" `
             -NoTypeInformation -Encoding UTF8

Работает поверх WinRM. Если доступа по WinRM нет — откройте порт 5985 групповой политикой, это стандартная практика для доменной среды.

Мини-кейс: поиск виновника блокировок учётки

В феврале 2026 года к нам обратилась бухгалтерская компания в Москве — 38 рабочих мест, сервер на Dell с Xeon Platinum 8280. У главбуха каждое утро блокировалась учётка. Хелпдеск провайдера четвёртый месяц разводил руками. Я подключился, запустил один запрос:

Get-WinEvent -ComputerName DC01 -FilterHashtable @{
  LogName='Security'; Id=4740
} -MaxEvents 20 | ForEach-Object {
  [PSCustomObject]@{
    Time      = $_.TimeCreated
    User      = $_.Properties[0].Value
    Source    = $_.Properties[1].Value
  }
}

Выяснилось: блокировки шли с IP офисного МФУ — у пользовательницы в настройках сканирования был сохранён старый пароль. Три месяца корп-поддержка не могла найти. Решение заняло 4 минуты на смену пароля в настройках устройства. За 15+ лет таких историй у меня десятки.

XPath-фильтры для сложных запросов

XPath даёт доступ к любому полю события. Пример — найти все запуски процессов с конкретным именем (требует включённого Process Tracking в auditpol):

Get-WinEvent -LogName Security -FilterXPath @"
*[System[EventID=4688] and
  EventData[Data[@Name='NewProcessName'] and contains(.,'mimikatz')]]
"@

Если не помните структуру XML, выгрузите событие и посмотрите:

(Get-WinEvent -LogName Security -MaxEvents 1 -FilterHashtable @{Id=4624}).ToXml()

Размер журнала и ротация

На продакшне я всегда увеличиваю размер журнала Security до 1–4 ГБ — стандартные 20 МБ вмещают несколько часов на загруженном контроллере домена, а это катастрофа при расследовании инцидента. Настройка через PowerShell:

wevtutil sl Security /ms:4294967296 /rt:false /ab:true
# /ms — максимальный размер в байтах (4 ГБ)
# /rt:false — при заполнении перезаписывать
# /ab:true — автоматическое резервирование

Дополнительно настройте архивирование на отдельный диск и ежемесячный выгруз в SIEM или хотя бы в холодное хранилище. У нас в дата-центре МТС через сетевую карту Mellanox 40G логи со всего парка сливаются на кластер бэкапов за считаные минуты.

Настроим централизованный сбор Windows-логов

Разверну Windows Event Forwarding с коллектором, фильтрами и ретенцией под ваши регуляторные требования. Поиск причин сбоев, анализ инцидентов, отчёты для ИБ — удалённо или на месте в Москве и области.

Телефон: +7 903 729-62-41
Telegram: @ITfresh_Boss
Семёнов Евгений Сергеевич, директор АйТи Фреш

FAQ — частые вопросы по Windows Event Log

Чем Get-WinEvent лучше Get-EventLog?
Get-WinEvent работает с современными каналами Applications and Services Logs, поддерживает XPath-фильтрацию на стороне провайдера и обрабатывает миллионы записей без загрузки в память.
Как отфильтровать события за последние сутки?
Параметр FilterHashtable со StartTime = (Get-Date).AddDays(-1). Фильтр уходит в Windows, а не в PowerShell — скорость на порядок выше.
Можно ли собирать Event Log с удалённых машин массово?
Да, через Invoke-Command или через Windows Event Forwarding. Для парка 20+ серверов лучше WEF с центральным коллектором.
Как найти событие по EventID и пользователю?
Комбинация FilterHashtable по Id и Where-Object по Properties или XPath-запроса по EventData. XPath предпочтительнее для частых задач.
Почему журнал Security растёт по 10 ГБ в день?
Обычно включён избыточный аудит — Object Access или Process Tracking. Проверьте auditpol /get /category:* и отключите лишние подкатегории.

Подпишитесь на рассылку ITfresh

Раз в неделю — практические гайды для руководителя IT и сисадмина: безопасность, 1С, миграции, резервные копии, лайфхаки из реальных проектов.

Реквизиты оператора персональных данных

ООО «АЙТИ-ФРЕШ», ИНН 7719418495, КПП 771901001. Юридический адрес: 105523, г. Москва, Щёлковское шоссе, д. 92, корп. 7. Контакт: info@itfresh.ru, +7 903 729-62-41. Оператор обрабатывает e-mail подписчика в целях рассылки информационных и рекламных материалов до момента отзыва согласия.