Я хочу сделать эквивалент:
tail -f
в Windows. Я прочитал это, но похоже, что нет возможности передавать журнал событий в потоковом режиме, поэтому он работает в бесконечном цикле и отображает события по мере их возникновения в командной строке. Есть ли какая-либо встроенная опция/флаг команды для этого в Windows?
🤔 А знаете ли вы, что...
С PowerShell можно управлять файлами, реестром, службами, процессами и многими другими аспектами Windows.
Эквивалентом tail -f
является Get-Content -Wait
. Но это не помогает, потому что вам все равно нужны ваши события в текстовом файле. Windows хранит свои события в файлах .evtx
по адресу C:\Windows\System32\winevt\Logs
, и они являются двоичными.
В качестве обходного пути вы можете периодически печатать последние x событий:
function Get-WinEventTail {
param(
$LogName,
$MaxEvents = 20
)
while ($true) {
Get-WinEvent -LogName $LogName -MaxEvents $MaxEvents | Select-Object TimeCreated, Message
Start-Sleep -Seconds 1
}
}
Get-WinEventTail -LogName System
Более сложный подход — использовать EventLogWatcher для записи входящих событий в текстовый файл и последующего отслеживания этого файла:
function Write-WinEventsToTempFile {
param(
$LogName
)
try {
$logFile = New-TemporaryFile
$query = [System.Diagnostics.Eventing.Reader.EventLogQuery]::new($LogName,[System.Diagnostics.Eventing.Reader.PathType]::LogName)
$watcher = [System.Diagnostics.Eventing.Reader.EventLogWatcher]::new($query)
$watcher.Enabled = $true
$action = {
$myEvent = Get-WinEvent -LogName $eventArgs.EventRecord.LogName | Where-Object {$_.RecordId -eq $eventArgs.EventRecord.RecordId}
"[$($myEvent[0].TimeCreated)]: $(($myEvent[0].Message -replace '\r\n', '') -replace '\t|\s{2,}', ' ')" | Out-File $event.MessageData -Append
}
$job = Register-ObjectEvent -InputObject $watcher -SourceIdentifier WriteWinEventsToTempFile -EventName 'EventRecordWritten' -MessageData $logFile -Action $action
Write-Host "Use `"Get-Content '$($logFile.FullName)' -Wait`" in another PowerShell window to tail the log. Press Ctrl+C, if you are done..."
Wait-Event -SourceIdentifier WriteWinEventsToTempFile
} finally {
Remove-Job $job -Force
Remove-Item $logFile
}
}
Write-WinEventsToTempFile -LogName System
Решение на основе [System.Diagnostics.Eventing.Reader.EventLogWatcher] в ответе stackprotector многообещающе, но несколько громоздко из-за необходимости использования временного файла, который необходимо читать отдельно.
Этого можно избежать с помощью следующей функции Trace-WinEvent
, которая передает любые новые добавленные записи событий непосредственно в конвейер:
function Trace-WinEvent {
param(
[Parameter(Mandatory)] [string] $LogName
)
$sourceId = 'TraceWinEvent' # self-chosen
try {
$query = [System.Diagnostics.Eventing.Reader.EventLogQuery]::new($LogName, 'LogName')
$watcher = [System.Diagnostics.Eventing.Reader.EventLogWatcher]::new($query)
$watcher.Enabled = $true
Write-Verbose "Registering for EventLogWatcher events for the '$LogName' log..."
Register-ObjectEvent -InputObject $watcher -SourceIdentifier $sourceId -EventName EventRecordWritten
Write-Verbose 'Waiting for such events indefinitely; use Ctrl+C to stop...'
while ($true) {
$evt = Wait-Event -SourceIdentifier $sourceId
$evt | Remove-Event
# Extract the event record.
$evtRec = $evt.SourceEventArgs.EventRecord
# Add a .Message NoteProperty member and output the decorated record.
$evtRec | Add-Member -PassThru Message $evtRec.FormatDescription()
}
}
finally {
Unregister-Event $sourceId
}
}
Вызовите его, например, следующим образом:
# Trace (monitor) the Application event log for newly created records
# and also capture them in variable $records.
# -Verbose provides verbose feedback.
# Use Ctrl-C to stop.
Trace-WinEvent Application -OutVariable records -Verbose
Пример вывода:
Примечание:
Потоковая передача в конвейер не только обеспечивает мгновенный вывод на консоль, но также позволяет программную обработку записей, которые являются экземплярами [System.Diagnostics.Eventing.Reader.EventLogRecord], в конвейере.
Чтобы прекратить отслеживание (мониторинг), нажмите Ctrl+C.
Реализация основана на:
Вызов Register-ObjectEvent без блока сценария -Action
, что ставит PowerShell в очередь событий для извлечения по требованию.
Это извлечение по требованию выполняется в бесконечном цикле, который вызывает Wait-Event для получения ожидающих событий по одному в блокирующем режиме.
Поскольку форматирование экземпляров EventLogRecord
в PowerShell для отображения зависит от наличия свойства .Message
ETS (типа NoteProperty
, которым Get-WinEvent автоматически украшает свои выходные объекты), приведенный выше код вручную декорирует каждый экземпляр, извлеченный из объекта события. таким образом, с помощью метода .FormatDescription()
, и выводит декорированный экземпляр в конвейер.
[*]