El título lo dice todo. He estado devolviendo el resultado de cada iteración de los dos bucles foreach a continuación (consulte las líneas Write-Host y Write-Output), pero la aplicación que está usando este script (Nagios) no puede manejar tantos datos. Por lo tanto, me gustaría devolver solo 1 salida a la vez. Básicamente, "Todas las aplicaciones están bien" o "Aplicaciones abajo: luego enumere las aplicaciones que no devuelven el código de respuesta 200". No tengo idea de cómo hacer esto, ya que conseguir que los bucles foreach funcionen en primer lugar fue todo un desafío para mí.

$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}
1
RaptorPete 16 oct. 2018 a las 15:19

2 respuestas

La mejor respuesta

Este es mi enfoque. SIN PROBAR. Solo para darte una idea con la que trabajar.

$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}

Explicaciones:

$appsDown = New-Object "System.Collections.Generic.HashSet[string]"

Cree una nueva instancia de . NET HashSet para guardar los nombres de las aplicaciones. (Es una colección desordenada donde cada valor se almacena solo una vez).

[void]$appsDown.Add($app)

Agrega el nombre de la aplicación a la colección. [void] está ahí para evitar que el valor de retorno del método se envíe a la canalización.

1
marsze 17 oct. 2018 a las 07:10

Esto puede ayudarlo a:

$list = @()
Foreach(x in y){
$item = @{}
If(x.error -eq 200){
$item.Name = x.Name
}
$obj = New-Object PSObject -Property $item
$list += $obj
}

Agregar estas partes te dejará con una lista de nombres de aplicaciones en la variable $list

0
Tourius 16 oct. 2018 a las 12:38