Я не хочу продолжать это, но несколько замечаний, которые я не могу сделать в комментарии.
w32tm.exe действительно может вернуть отрицательное число, например -1.001755. Это не учитывается в последнем ответе. Кроме того, я бы использовал -ge
& -le
вместо -gt
& -lt
, так как есть крайний случай различия + + - ровно 1 секунда. Я знаю, что это, вероятно, тривиально в таком сценарии, но это также ничего не стоит, чтобы быть тщательным.
Я бы установил sh $mailParams
га sh до For l oop и только сбросить значение body в блоке if.
Я не совсем уверен, почему мы используем метод [Double]::Parse()
. Я работаю в США, где меньше нужны возможности глобализации. Однако в быстром тестировании я не вижу никакой разницы в результате. Рад, что это объяснили дальше.
Ключом к этому была возможность взглянуть назад через массив относительно строки NTP. То, как мы сопоставляем / идентифицируем линию и разделяем ее, является вопросом предпочтения. Тем не менее, я нашел недостаток в моем подходе, потому что в некоторых случаях может отображаться «NTP: ошибка». Это достаточно просто исправить без более сложного RegEx. Я добавил строки с ошибками в пример вывода, чтобы охватить его в следующих примерах.
Я думаю, вам нравится более интенсивный подход RegEx, и, конечно, его использование помогает нам учиться. Поэтому я приведу оба приведенных ниже примера ниже.
Вы также должны решить, хотите ли вы получать несколько уведомлений по электронной почте или только 1 электронное письмо со всеми данными предупреждений за один запуск. Поскольку все мы страдаем от некоторой степени перегрузки электронной почты, я предполагаю, что это последнее, но я поместил туда логическую переменную, чтобы вы могли решить для себя.
Я сделал комментарий в своем первоначальном ответе на poli sh до $CurrentServer
. @ Тео сделал это с .TrimEnd(':')
, однако я думаю, что мы можем пойти дальше. Сначала я подумал, что это номер порта, который я могу сделать что-то вроде -replace ":\d{1,5}:"
, которое будет разделять двоеточие в конце и конце на 1-5 цифр. Это сработало, но не кажется правильным. Возможность отклонения NTP от хорошо известного порта 123 крайне мала. Итак, вместо этого давайте нарежем его, используя буквальное совпадение типа -replace ":123]:","]"
Примечание: .Replace(":123]:", "]")
, вероятно, будет работать так же хорошо.
Пример Вывод из w32tm:
# Sample Output, in practice set this to the output of w32tm.exe
$W32t_Output =
@(
'server2.mydomain.local[192.168.22.22:123]:'
' ICMP: 1ms delay'
' NTP: +0.0017247s offset from server1.mydomain.local'
' RefID: server1.mydomain.local [192.168.22.122.]'
' Stratum: 3'
'server2.mydomain.local[192.168.22.22:123]:'
' ICMP: 1ms delay'
' NTP: -1.0017247s offset from server1.mydomain.local'
' RefID: server1.mydomain.local [192.168.22.122.]'
' Stratum: 3'
'server2.mydomain.local[192.168.22.22:123]:'
' ICMP: 1ms delay'
' NTP: +2.0017247s offset from server1.mydomain.local'
' RefID: server1.mydomain.local [192.168.22.122.]'
' Stratum: 3'
'server2.mydomain.local[192.168.200.200:123]:'
' ICMP: 0ms delay'
' NTP: error ERROR_TIMEOUT - no response from server in 1000ms'
'DownServer.mydomain.local [error WSAHOST_NOT_FOUND]'
)
Пример 1 с использованием моего оригинальный подход:
# > Set $OneAlert to true if you want 1 alert for all the interesting time variances per run.
# > Set to false if you want a single alert for each interesting variance encountered per run.
$OneAlert = $true
$Body = [Collections.ArrayList]@()
$AlertThreshold = 1 # Number of seconds before an alert...
$mailParams =
@{
To = 'someone@yourdomain.com'
From = 'ntpchecker@yourdomain.com'
SmtpServer = 'mailserver.yourdomain.com'
Subject = 'Alert Server Time Difference'
Body = ''
Priority = 'High'
}
For( $i = 0; $i -lt $W32t_Output.Length; ++$i )
{
$CurrentLine = $W32t_Output[$i].Trim()
If( $CurrentLine -match '^NTP: ' -and $CurrentLine -notmatch 'error' )
{
$CurrentLineFields = $CurrentLine.Split(' ') # Break up the NTP line, as long as the output is predictable this should work.
[Double]$OffSet = $CurrentLineFields[1].Replace('s','') # The second index should be the offset, clean it up to be a number...
$DiffServer = $CurrentLineFields[-1] # Last thing on the current line should be the server is offset from.
$CurrentServer = $W32t_Output[$i-2] -replace ":123]:","]" # Look back through the output array to get the current server.
# Logic for echoing and/or email alerting:
If( $OffSet -ge $AlertThreshold -or $OffSet -le -$AlertThreshold )
{
If($OneAlert)
{
[Void]$Body.Add( "Alert : $CurrentServer time offset $Offset seconds from $DiffServer !" )
}
Else
{
$mailParams['Body'] = "Alert : $CurrentServer time offset $Offset seconds from $DiffServer !"
Send-MailMessage @mailParams
}
}
}
}
# $Body will only be populated if $OneAlert is true
If( $Body )
{
$mailParams['body'] = $Body -join "`r`n"
Send-MailMessage @mailParams
}
Пример 2, дополнительно объединяющий подход @Theo:
# > Set $OneAlert to true if you want 1 alert for all the interesting time variances per run.
# > Set to false if you want a single alert for each interesting variance encountered per run.
$OneAlert = $false
$Body = [Collections.ArrayList]@()
$AlertThreshold = 1 # Number of seconds before an alert...
$mailParams =
@{
To = 'someone@yourdomain.com'
From = 'ntpchecker@yourdomain.com'
SmtpServer = 'mailserver.yourdomain.com'
Subject = 'Alert Server Time Difference'
Body = ''
Priority = 'High'
}
for( $i = 0; $i -lt $output.Count; $i++ ) {
if ($output[$i] -match 'NTP:\s+([+-]?\d+(?:\.\d+)?)s') {
$seconds = [double]::Parse($matches[1], [cultureinfo]::InvariantCulture)
# Adjusted the if condition a little:
if ( $seconds -ge $AlertThreshold -or $seconds -le -$AlertThreshold ) {
$currentServer = $output[$i - 2] -replace ":123]:","]" # changed a little
$refServer = ($output[$i] -split ' ')[-1]
If($OneAlert) # prepare to send an email alert
{
[Void]$Body.Add( "Alert: $currentServer time offset $seconds seconds from $refServer !" )
}
Else
{
$mailParams['body'] = "Alert: $currentServer time offset $seconds seconds from $refServer !"
Send-MailMessage @mailParams
}
}
}
}
# $Body will only be populated if $OneAlert is true
If( $Body )
{
$mailParams['body'] = $Body -join "`r`n"
Send-MailMessage @mailParams
}
Очевидно, это маленькое голубое небо, и я, вероятно, увлекся. В любом случае, дайте мне / нам знать, что вы думаете.