Название говорит само за себя. Я возвращал выходные данные каждой итерации обоих приведенных ниже циклов foreach (см. Строки Write-Host и Write-Output), но приложение, использующее этот сценарий (Nagios), не может обрабатывать такой объем данных. Поэтому я хотел бы возвращать только 1 вывод за раз. Обычно «Все приложения в порядке» или «Приложение (а) не работает: затем перечислить приложения, не возвращающие код ответа 200». Я понятия не имею, как это сделать, поскольку заставить работать циклы foreach в первую очередь было для меня сложной задачей.
$ok = 0
$warning = 1
$critical = 2
$unknown = 3
$appPool = get-webapplication
$errorcode = 0
$time_errorcode = 0
foreach($a in $appPool) {
$app = $a.Attributes[0].Value;
$url = "http://localhost$app/apitest/index"
$HTTP_Request = [System.Net.WebRequest]::Create($url)
$HTTP_Response = try{ $HTTP_Request.GetResponse() }catch {$exceptionMessage = $_.Exception.Message
$exceptionItem = $app}
[int]$HTTP_Response.StatusCode -ne 200
$statuscode = [int]$HTTP_Response.StatusCode
Write-Host "$app status code: $statuscode"
if ($HTTP_Response.StatusCode.value__ -ne 200) {
[int]$errorcode = 1
}
}
foreach($t in $appPool){
$app = $t.Attributes[0].Value;
$url = "http://localhost$app/apitest/index"
$output = "$PSScriptRoot\10meg.test"
$start_time = Get-Date
try {Invoke-WebRequest -Uri $url -OutFile $output} catch {
$exceptionMessage = $_.Exception.Message
$exceptionItem = $app
Write-Output "$app error: $exceptionMessage"}
Write-Output "$app Time taken: $((Get-Date).Subtract($start_time).milliSeconds) millisecond(s)"
$timetaken = $((Get-Date).Subtract($start_time).milliSeconds)
if ($timetaken.StatusCode.value__ -ge 500) {
[int]$time_errorcode = 1
}
}
#Uncomment for testing
#Write-Output $time_errorcode
#Write-Output $errorcode
if (($errorcode -eq 0 -and $time_errorcode -eq 0)){exit $ok}
if (($errorcode -eq 1 -and $time_errorcode -eq 0)){exit $critical}
if (($errorcode -eq 0 -and $time_errorcode -eq 1)){exit $warning}
if (($errorcode -eq 1 -and $time_errorcode -eq 1)){exit $critical}
else {exit $unknown}
$timetaken.StatusCode.value__ -ge 500 - это явно опечатка. Также объясните, почему у вас петли 2. Кроме того, то, что вы спросили, банально, я могу помочь вам, если у меня будет больше информации.
@marsze, это не опечатка. Этот раздел кода предназначен для проверки того, занимает ли загрузка приложения более 500 мс. Собственно поэтому и у меня 2 петли. 1, чтобы проверить код ответа, и секунду, чтобы проверить время загрузки. Какая дополнительная информация вам нужна?
$timetaken - это число (кстати, вы, вероятно, хотели использовать TotalMilliseconds) и не имеет свойства StatusCode. Вероятно, вы имели в виду: if (((Get-Date) - $start_time).TotalMilliseconds -gt 500)Хорошо, я попробую. Как насчет того, чтобы иметь возможность писать-выводить отдельные приложения, когда они ошибаются (или когда они достигают 500 во втором цикле)? Я хотел бы написать только те приложения, которые потерпели неудачу, а не все они, чтобы сохранить данные, о которых сообщается.





Это может вам помочь:
$list = @()
Foreach(x in y){
$item = @{}
If(x.error -eq 200){
$item.Name = x.Name
}
$obj = New-Object PSObject -Property $item
$list += $obj
}
Добавление этих частей оставит вам список имен приложений в переменной $list.
Похоже, у вас есть этот список, только если ошибка равна 200. Как мне вернуть имя приложения, если ошибка отличается от 200?
Оператор if, который я добавил здесь, является всего лишь примером. Это больше, чтобы показать вам, как создать список. Вам нужно добавить переменные, список, элемент и создание объекта в соответствующие места.
Вот мой подход. НЕПРОВЕРЕНО. Просто чтобы дать вам представление о работе.
$appPool = Get-WebApplication
$errorcode = 0
$time_errorcode = 0
# Using a hashset ensures every app is contained only once
$appsDown = New-Object "System.Collections.Generic.HashSet[string]"
foreach($a in $appPool) {
$app = $a.Attributes[0].Value;
$url = "http://localhost$app/apitest/index"
### Test response code ###
$HTTP_Request = [System.Net.WebRequest]::Create($url)
$HTTP_Response = $null
try {
$HTTP_Response = $HTTP_Request.GetResponse()
} catch {
# for test
Write-Host $_
}
if ($null -eq $HTTP_Response -or [int]$HTTP_Response.StatusCode -ne 200 ) {
[int]$errorcode = 1
[void]$appsDown.Add($app)
}
### Test response time ###
$output = "$PSScriptRoot\10meg.test"
$start_time = Get-Date
$timetaken = -1
try {
Invoke-WebRequest -Uri $url -OutFile $output
$timetaken = ((Get-Date) - $start_time).TotalMilliSeconds
} catch {
# for test
Write-Host $_
}
if ($timetaken -lt 0 -or $timetaken -ge 500) {
[int]$time_errorcode = 1
[void]$appsDown.Add($app)
}
}
# Output the results here
if ($appsDown.Count -eq 0) {
Write-Output "All apps okay"
}
else {
Write-Output ($appsDown.Count.ToString() + "app(s) down")
$appsDown | sort | foreach {
Write-Output $_
}
}
if (($errorcode -eq 0 -and $time_errorcode -eq 0)){exit $ok}
if (($errorcode -eq 1 -and $time_errorcode -eq 0)){exit $critical}
if (($errorcode -eq 0 -and $time_errorcode -eq 1)){exit $warning}
if (($errorcode -eq 1 -and $time_errorcode -eq 1)){exit $critical}
else {exit $unknown}
Пояснения:
$appsDown = New-Object "System.Collections.Generic.HashSet[string]"
Создайте новый экземпляр .NET HashSet для хранения имен приложений. (Это неупорядоченная коллекция, в которой каждое значение сохраняется только один раз.)
[void]$appsDown.Add($app)
Добавьте название приложения в коллекцию. [void] предназначен для предотвращения отправки возвращаемого значения метода в конвейер.
Это прекрасно и работает как шарм, спасибо. Я также хотел бы понять это, поэтому у меня есть несколько дополнительных вопросов. Прежде всего, что делает этот раздел? [void]$appsDown.Add($app) Во-вторых, я этого раньше не видел, для чего это тоже? New-Object "System.Collections.Generic.HashSet[string]"
@RaptorPete Я добавил несколько пояснений к своему ответу, надеюсь, это поможет. Если это решило вашу проблему, отметьте мой ответ как принятый.
Сегодня я только понимаю, что ваш пример сообщит, что приложение «не работает», если время загрузки превышает 500 мс. В конечном итоге я бы хотел, чтобы он включал отдельный вывод для time_errorcode, а не просто «приложение не работает». Что-то вроде "$currentapp warning - download time 850ms" При этом в вашем операторе if / else, который выводит результаты, я не могу найти способ легко включить этот раздел. Вы сообщаете о любых приложениях в коллекцию, но можно ли также сообщить о конкретном времени в эту коллекцию и вывести их?
@RaptorPete У вас есть несколько вариантов. Вы можете создавать несколько коллекций, наборов пользовательских объектов, вывод на итерацию и т. д. Все зависит от того, что именно вы хотите выводить и как. Попробуйте, и если вам нужна дополнительная помощь, не стесняйтесь расширять исходный вопрос.
Моим первым инстинктом было бы предложить использовать
Where-Object. Я не уверен, где и как включить это в ваш пример. Проще говоря, сохраните все в массиве, а затем используйтеWhere-Objectдля проверки, чтобы определить, какой вывод отображать.