Анализ журналов 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 / 4625 | Security | Успешный / неуспешный вход |
| 4740 | Security | Блокировка учётки |
| 4720 / 4726 | Security | Создание / удаление пользователя |
| 7034 / 7036 / 7040 | System | Сбой службы / старт-стоп / смена типа запуска |
| 6005 / 6006 / 6008 | System | Старт / штатная остановка / внеплановая перезагрузка |
| 41 | System (Kernel-Power) | Машина ушла в ребут без штатного shutdown |
| 1000 / 1001 | Application | Аварийное завершение приложения / 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:* и отключите лишние подкатегории.