Powershell: разбить массив на пары и сбросить, если не чередуется
У меня есть скрипт Powershell, который использует Get-EventLog
искать события 6005
, 6006
, а также 6008
на удаленных серверах; после небольшой манипуляции он возвращает результаты в массиве.
$eventData += Get-EventLog -computerName $server_name -LogName system `
-After $prevMonthBegin -Before $prevMonthEnd |
Where-Object `
{ $_.eventid -eq 6005 -OR $_.eventID -eq 6006 -OR $_.eventID -eq 6008 } |
Select timegenerated, eventid, message, index, recordid | sort-object timegenerated
Я перебираю результаты и назначаю down
или же up
к $eventData.message
поле и сортировать его снова timegenerated
Это возвращает массив как так (извинения за форматирование):
$eventData | Sort-Object timegenerated | format-table
TimeGenerated EventID Индекс сообщения
------------- ------- ------- ----- --------
03.08.2014 5:30:02 утра 6006 вниз 0
03.08.2014 5:30:47 6005 до 0
24.08.2014 5:31:00 утра 6005 до 0
31.08.2014 2:34:59 утра 6008 вниз 1
31.08.2014 5:30:04 утра 6006 вниз 0
31.08.2014 5:30:59 утра 6005 до 0
31.08.2014 5:36:26 утра 6005 до 0
Как я могу создать новый массив из этих результатов и организовать TimeGenerated
на пары вверх / вниз? Я бы предпочел не обращать внимания на первое событие массива, если оноup
(так что всегда есть down
затем up
в парах), но я могу обойти это. Более важно никогда не иметь два последовательных down
или же up
события, как в примере вывода выше.
Я думал о, возможно, перебирая события и переключая временную переменную между 1
а также 0
(или же up
а также down
) но это кажется неуклюжим, и я просто не могу заставить что-либо работать. Это не должно быть так сложно, но именно поэтому я и прошу помощи. Дайте мне знать, было бы полезно предоставить больше кода; есть довольно много этого, и я не хотел просто сбрасывать страницы этого.
Вот пример формата для массива, который я хотел бы иметь. Метод, который я использую, связывает эти события как 12121212, не смотря на то, какие это типы событий. Таким образом, в приведенном выше примере, последняя пара событий будет рассчитывать время простоя, когда оно не существует, потому что было два up
(6005) события.
Downtime Uptime CrashEvent?
8/3/2014 5:30:02 AM 8/3/2014 5:30:47 AM 0
8/24/2014 5:31:00 AM 8/31/2014 2:34:59 AM 0
8/31/2014 2:34:59 AM 8/31/2014 5:30:04 AM 1
8/31/2014 5:30:59 AM 8/31/2014 5:36:26 AM 0
2 ответа
Вот ответ, как это сделать, чтобы пропустить повторяющиеся записи. Тем не менее, вы, вероятно, захотите настроить запрашиваемые вами события, в противном случае вы в конечном итоге столкнетесь с условиями понижения / повышения, возникающими одновременно.
$Events = Get-EventLog -LogName system |
Where-Object { $_.eventid -eq 6005 -OR $_.eventID -eq 6006 -OR $_.eventID -eq 6008 } |
Select timegenerated, eventid, message, index, recordid | sort-object timegenerated
[array]$FullObj = [pscustomobject] @{
'Time' = ''
'Status' = ''
'Message' = ''
}
Foreach ($Event in $Events)
{
If ($Event.Message -eq 'The Event log service was started.' -and $fullobj.status[-1] -ne 'UP')
{
[array]$FullObj += [pscustomobject] @{
'Time' = $Event.TimeGenerated
'Status' = 'UP'
'Message' = $Event.Message
}
}
Elseif ($fullobj.status[-1] -eq 'UP' -and $fullobj.Message[-1] -notlike "The previous system shutdown*")
{
[array]$FullObj += [pscustomobject] @{
'Time' = $Event.TimeGenerated
'Status' = 'DOWN'
'Message' = $Event.Message
}
}
}
$FullObj | select time,status
Хорошо, это должно выбрать последнее из любого события "Вниз" или "Вверх" перед следующим типом противоположного типа (последний "Вниз" перед "Вверх" и последний "Вверх" перед "Вниз"), который, я думаю, является тем, что вы хотели. В основном совпадают каждый раз, когда система выходит из строя, со временем, когда она возвращалась, используя последнее уведомление о времени безотказной работы / простоях, если их несколько. Я думаю, что все ваше "Отмена первого любого последовательного дублированного типа события" ошибочно, но это именно так.
Коллекция событий, продублированная из Noah Sparks, с аргументом Select немного урезана. Затем он переходит в Switch, создавая пользовательский объект всякий раз, когда происходит событие Downtime, а затем устанавливает время работы для каждого события uptime и выводит его всякий раз, когда происходит следующее событие простоя, и начинает заново.
$Events = Get-EventLog -LogName system |
Where-Object { $_.eventid -eq 6005 -OR $_.eventID -eq 6006 -OR $_.eventID -eq 6008 } |
Select timegenerated, eventid | sort-object timegenerated
$record=$null
$Output = Switch($Events){
{$_.EventID -match "600(6|8)"}{if(![string]::IsNullOrEmpty($Record.up)){$record}
$Record=[pscustomobject][ordered]@{
'Down'=$_.timegenerated
'Up'=$null
'Expected'=If($_.EventID -eq 6006){$true}else{$false}
}}
{$_.EventID -eq "6005"}{$Record.Up = $_.TimeGenerated}
}
$Output += $record
$Output
Лично я бы пошел с первым временем безотказной работы даже после того, как произошел случай простоя, но это только я. Это займет другое кодирование. Во всяком случае, результаты этого выглядят так (используя мои собственные записи журнала событий):
Down Up Expected
---- -- --------
11/20/2013 8:47:42 AM 11/20/2013 8:49:11 AM True
11/20/2013 3:50:14 PM 12/13/2013 9:14:52 AM True
12/13/2013 9:26:21 AM 12/13/2013 9:27:42 AM False
12/13/2013 3:40:07 PM 12/13/2013 3:41:31 PM True
1/9/2014 1:13:31 PM 1/16/2014 12:38:08 PM True
1/16/2014 12:39:21 PM 1/16/2014 12:48:44 PM True
Если вы посмотрите на второй список, я знаю, что мой компьютер не был сбит с 11/20 до 12/13, но отбрасывает первый из последовательных дубликатов, как это происходит. Если бы мы этого не сделали, это показало бы, что система возвращается в исходное состояние через одну минуту после сбоя, что гораздо более вероятно для моего компьютера.