Скрипт Powershell: создание цикла для ResponseTime

У меня возникла проблема с тем, как мои результаты пинга "выкатились" на экран. Я использую этот код:

$servers = "192.168.2.10","192.168.2.80","192.168.2.254"
$collection = $()
foreach ($server in $servers)
{
    $status = @{ "ServerName" = $server; "TimeStamp" = (Get-Date -f s) }
    $testconnection = (Test-Connection $server -Count 1 -ea 0)
    $response = ($testconnection | select ResponseTime)
    if ($response)
    {
        $status["Results"] = "Up"
        $status["Responsetime"] = $response
    }
    else
    {
        $status["Results"] = "Down"
    }
    New-Object -TypeName PSObject -Property $status -OutVariable serverStatus
    $collection += $serverStatus

}
$collection | Export-Csv -Path ".\ServerStatus.csv" -NoTypeInformation

Я хотел бы создать цикл для ResponseTime. Код, который я использую сейчас, дает один ответ. Когда я даю счет 2, он печатает ResponseTime рядом с каждым IP-адресом.

Выход:

TimeStamp                                             Responsetime                                          Results                                               ServerName                                           
---------                                             ------------                                          -------                                               ----------                                            
2014-10-22T23:30:17                                   {@{ResponseTime=6}, @{ResponseTime=4}}                Up                                                    192.168.2.10                                         
2014-10-22T23:30:18                                                                                         Down                                                  192.168.2.80                                         
2014-10-22T23:30:25                                   {@{ResponseTime=1}, @{ResponseTime=3}}                Up                                                    192.168.2.254

То, что я хочу, это чтобы скрипт печатал каждый ResponseTime под друг другом так:

TimeStamp               Responsetime              Results        ServerName                                           
---------               ------------              -------        ----------                                           
2014-10-22T23:11:50     @{ResponseTime=419}       Up             192.168.2.10                                         
2014-10-22T23:11:51     @{ResponseTime=415}       Up             192.168.2.10                                         
2014-10-22T23:11:51                               Down           192.168.2.80
2014-10-22T23:11:52     @{ResponseTime=470}       Up             192.168.2.254  
2014-10-22T23:11:52     @{ResponseTime=7}         Up             192.168.2.254

Или вот так:

TimeStamp               Responsetime              Results        ServerName                                           
---------               ------------              -------        ----------                                           
2014-10-22T23:11:50     @{ResponseTime=419}       Up             192.168.2.10                                         
2014-10-22T23:11:51                               Down           192.168.2.80                                         
2014-10-22T23:11:51     @{ResponseTime=415}       Up             192.168.2.254
2014-10-22T23:11:52     @{ResponseTime=470}       Up             192.168.2.10
2014-10-22T23:11:51                               Down           192.168.2.80  
2014-10-22T23:11:52     @{ResponseTime=7}         Up             192.168.2.254

Неважно, какой из них, я предпочитаю второй

Не могли бы вы помочь мне с этим вопросом. Даже если это невозможно, скажи мне тоже.

Спасибо Крис

3 ответа

Решение

Я перезвоню позже, не потому что другой ответ неверен в любом случае, они оба функциональны, но тем более, что никто не указал, что вы воссоздаете колесо.

Вы проверяете соединение и указываете на него ошибку, которая продолжает молча, оставляя вашу переменную нулевой. Затем вы должны проверить, имеет ли переменная результаты, и обработать ее одним способом, или она не обрабатывает другим способом. То, что вы только что сделали, - это ваш собственный сценарий Try/Catch. Если вы действительно используете ошибку для остановки, вы можете использовать встроенный Try/Catch. Рассмотрим этот подход:

$servers = "www.google.com","localhost","www.amazon.com"
$collection = @()
foreach ($server in $servers)
{
    Try{    
        $testconnection = Test-Connection $server -Count 2 -ErrorAction Stop
        $testconnection | ForEach{$collection += New-Object PSObject -Property ([ordered]@{
            'TimeStamp' = Get-Date -Format s
            'Server' = $server
            'ResponseTime' = $_.responsetime
            'Results' = 'Up'})
        }
    }
    Catch{
        $collection += New-Object PSObject -Property ([ordered]@{
            'TimeStamp' = Get-Date -Format s
            'Server' = $server
            'ResponseTime' = $null
            'Results' = 'Unreachable'
        })
    }

}
$collection #| Export-Csv -Path ".\ServerStatus.csv" -NoTypeInformation

Он пытается пропинговать сервер и, если может, добавляет пользовательский объект в массив $collection с нужной информацией. Если эхо-запрос не выполняется, он также добавляет объект в $collection, показывающий, что сервер недоступен.

Кроме того, у вас было $collection = $(), Я предполагаю, что вы пытались создать пустой массив, что сделано правильно $collection = @() (исправлено в предложенном мной коде). Теперь я прокомментировал Export-CSV, чтобы увидеть результаты. Вот что я увидел:

TimeStamp                      Server                            ResponseTime Results
---------                      ------                            ------------ -------
2014-10-22T17:54:22            www.google.com                               9 Up
2014-10-22T17:54:22            www.google.com                              12 Up
2014-10-22T17:54:23            localhost                                    0 Up
2014-10-22T17:54:23            localhost                                    0 Up
2014-10-22T17:54:27            www.amazon.com                                 Unreachable

Амазон не позволил мне пропинговать его, поэтому он показывает, что он недоступен.

Переходя к тому, почему ваши желаемые результаты непрактичны... То, что вы описываете, показывает, как вы пингуете свои серверы и получаете результаты от них в непоследовательное время. Для этого вам придется сделать -count 1и дважды выполните цикл ForEach, чтобы он пропинговал сервер 1 для 1 результата, затем сервер 2 для 1 результата, затем сервер 3 для 1 результата. Затем он возвращается и проверяет сервер 1 для второго результата, затем сервер 2 для второго результата, а затем сервер 3 для второго результата. Я полагаю, что если вы хотите сделать это, то это даст желаемые результаты, вам нужно будет сделать что-то вроде этого:

$servers = "www.google.com","localhost","www.amazon.com"
$collection = @()
$count = 2
for($i=1;$i -le $count;$i++){
    ForEach($server in $servers){
        do stuff to ping servers as described above, except change -count to 1
    }
}
$collection | export-CSV '.\ServerStatus.csv' -notype

Это даст вам желаемые результаты, но это медленнее. Если вам придется запускать это на нескольких серверах, это будет заметно медленнее. Только для этих трех перечисленных серверов весь процесс прошел путь от 3,7240945 секунд до 7,6104075 секунд (примерно вдвое).

Вместо

$response = ($testconnection | select ResponseTime)
if ($response)
{
    $status["Results"] = "Up"
    $status["Responsetime"] = $response
}

делать

if($testconnection)
  {
    $testconnection | % {
    $status = @{"ServerName" = $server; "TimeStamp" = (Get-Date -f s); "Results" = "Up"; "Responsetime"= $_.responsetime}; 
    New-Object -TypeName PSObject -Property $status -OutVariable serverStatus;
    $collection += $serverStatus }
  }
else
  {
    $status = @{"ServerName" = $server; "TimeStamp" = (Get-Date -f s); "Results" = "Down"};
    New-Object -TypeName PSObject -Property $status -OutVariable serverStatus;
    $collection += $serverStatus 
  }

Проблема в том, что $testconnection или в вашем случае $response это массив, если количество Test-Connection больше 1, поэтому вы должны пройтись по нему и добавить отдельные записи в свою коллекцию.

Кроме того, чтобы получить значение вместо тарабарщины, которую вы получаете, вы должны позвонить .responsetime имущество.

В надежде, что я не усложняю, я представляю это решение.

$servers = "10.50.10.100","8.8.8.8","169.254.54.1"

$servers | ForEach-Object{
    $server = $_
    $timeStamp = (Get-Date -f s)
    $testconnection = Test-Connection $server -Count 2 -ErrorAction 0
    If(!$testconnection){
            $props = @{
                Server = $server
                TimeStamp = $timeStamp
                ResponseTime = ""
                Results = "Down"
            }

            New-Object -TypeName PSObject -Property $props

    } Else {
        $testconnection | ForEach-Object{
            $_ | Select-Object @{l='Server';e={$server}},@{l='TimeStamp';e={$timeStamp}},@{l='ResponseTime';e={$_.ResponseTime}},@{l='Results';e={"Up"}}
        }
    }
} | Export-Csv -Path ".\ServerStatus.csv" -NoTypeInformation

Итак, ваша логика все еще здесь, но, как вы можете видеть, некоторые вещи были изменены. Пол был прав, в том, что вам нужно было зацикливаться на каждом ResponseTime элемент у вас был. Я также сделал это, но с другим подходом, который, если не сказать больше, покажет вам некоторые возможности PowerShell. Нарушение кода

  1. труба $servers в ForEach-Object, ForEach in работает нормально, но я хотел пропустить сохранение переменных и просто выводить их прямо в Export-CSV вот почему я изменил это.
  2. Так что если вы используете Test-Connection на сервере, который не существует или по какой-либо причине возникают ошибки, вам нужно создать объект для его представления. Используя нужные свойства, создайте объект с необходимыми значениями. Это вывод на канал вместо использования временной переменной.
  3. Если проверка соединения прошла успешно, нам нужно вывести число или переменные, соответствующие количеству возвратов.
  4. Продолжая с № 3, мы используем Select-Object для вывода желаемых значений. Я стою за метку, а е за выражение. Да, вы можете просто использовать другую переменную $ props. Просто иллюстрирую еще один вариант.
  5. Так как мы изменили ForEach на первом этапе мы можем просто вывести прямо в Export-CSV

Образец вывода

Server       TimeStamp           ResponseTime Results
------       ---------           ------------ -------
10.50.10.100 2014-10-22T20:22:01 0            Up     
10.50.10.100 2014-10-22T20:22:01 0            Up     
8.8.8.8      2014-10-22T20:22:02 43           Up     
8.8.8.8      2014-10-22T20:22:02 39           Up     
169.254.54.1 2014-10-22T20:22:03              Down   
Другие вопросы по тегам