要添加到 Rys 的答案,Logstash-Forwarder 本身并不读取 Windows 事件日志。在研究如何解决这个问题时,我发现了 Sean-M 的这个要点。
我修改了他的原始脚本,以便 Powershell 脚本启动 LSF,然后将事件日志通过管道传输到标准输入。然后我将 NSSM 指向脚本并将其作为服务运行。如果您的配置文件设置如下:
{
"network": {
"servers": [ "<logstash IP>:5000" ],
"timeout": 15,
"ssl ca": "C:/path/to/logstash-forwarder.crt"
},
"files": [
{
"paths": [
"C:/inetpub/logs/LogFiles/W3SVC*/*.log"
],
"fields": { "type": "iis-w3svc" }
},
{
"paths": [
"-"
],
"fields": { "type": "windows-event" }
}
]
}
LSF 将捕获 JSON 输入并将其发送到 Logstash。下面的 Powershell 代码**:
#Requires -Version 3
param (
[string]$lognames
)
#reading security log requires elevated privileges so only read Application and System for now
[string[]]$logname = $("Application", "System" )
if ($lognames)
{
[string[]]$logname = $lognames -split ", "
}
##################################
# Functions #
##################################
function EvenSpace{
param ($word)
$tabWidth = 48
$wordTabs = $tabWidth - $word.Length
$tabNum = [Math]::Floor($($wordTabs/4)) / 2
("`t" * $tabNum)
}
## Read events, write to file
function ReadEvents {
param ([hashtable]$filter, [string]$OutFile=[String]::Empty)
## Make it look pretty if writting to stdout
try {
[object[]]$data = Get-WinEvent -FilterHashtable $filter -ErrorAction SilentlyContinue | sort RecordId
[int]$count = 0
if ((-not $data -eq $null) -or ($data.Count -gt 0)) {
$count = $data.Count
}
Write-Verbose ("Log: $($filter["LogName"])" + (EvenSpace -word $filter["LogName"]) + "Count: $count")
}
catch {
$Error[0]
Write-Verbose ""
Write-Verbose "Filter:"
$filter
return
}
if ($data.Count -gt 0) {
foreach ($event in $data) {
$json = $event | ConvertTo-Json -Compress
#$jsonbytes = @($json)
#$process.StandardInput.BaseStream.Write($jsonbytes,0,$jsonbytes.Count)
Write-Verbose $json
$process.StandardInput.WriteLine($json)
}
}
}
## Use a try/catch/finally to allow for the inputs to be closed and the process stopped
[System.Diagnostics.Process]$process = $null
$endTime = Get-Date
try
{
## Prepare to invoke the process
$processStartInfo = New-Object System.Diagnostics.ProcessStartInfo
$processStartInfo.FileName = (Get-Command .\logstash-forwarder.exe).Definition
$processStartInfo.WorkingDirectory = (Get-Location).Path
$processStartInfo.Arguments = "-config logstash-forwarder.conf"
$processStartInfo.UseShellExecute = $false
## Always redirect the input and output of the process.
## Sometimes we will capture it as binary, other times we will
## just treat it as strings.
$processStartInfo.RedirectStandardOutput = $true
$processStartInfo.RedirectStandardInput = $true
$process = [System.Diagnostics.Process]::Start($processStartInfo)
##################################
# Main Logic #
##################################
## Loop to capture events
while ($true) {
[String]::Empty | Write-Verbose
Start-Sleep -Seconds 5
$startTime = $endTime
[TimeSpan]$diff = (Get-Date) - $startTime
if ($diff.TotalHours -gt 1) {
$endTime = $startTime + (New-TimeSpan -Minutes 30)
}
else {
$endTime = Get-Date
}
Write-Verbose "Starting timespan $($startTime) -> $($endTime)"
## Supports reading multiple logs
if ($logname.Count -gt 1) {
foreach ($log in $logname) {
ReadEvents -filter @{LogName=$log; StartTime=$startTime; EndTime=$endTime} -OutFile $output
}
}
else {
ReadEvents -filter @{LogName=$logname; StartTime=$startTime; EndTime=$endTime} -OutFile $output
}
}
}
catch
{
Write-Error $error[0]|format-list -force
throw $_.Exception
}
finally
{
if($process)
{
$process.StandardInput.Close()
$process.Close()
}
}
** 该脚本并没有真正处理 LSF 失败,但它现在服务于我的目的。