Сделать скрипт более эффективным с помощью -asjob - PullRequest
1 голос
/ 06 марта 2012

У меня есть строчный скрипт aprox 1000, который проходит через все серверы в AD.Сценарий проверяет связь с каждым сервером и выполняет множество WMI-запросов, если ping = ok.Мой сценарий сохраняет результаты в хеш-таблице, которую я выводил в CSV в конце сценария.Это работает, но это неаккуратно. Мы говорим около двух часов.Я пытался сделать это более эффективным, и я думаю - задание звучит как хорошая идея.

Но могу ли я сделать это как параллельную работу?Будет ли мой сервер обрабатывать нагрузку?И есть ли способ сделать это?

Надеясь на ввод данных, пока я жду, пока мой скрипт запустит свой цикл ..

РЕДАКТИРОВАТЬ

Мое мнение таково, что скрипт ждетдля test-connection (ping) вернуть true или false.Я хотел бы запустить несколько пингов одновременно.

РЕДАКТИРОВАТЬ 2

( ПРИМЕЧАНИЕ: Я начал отдельный вопрося чувствую, что на мой первоначальный вопрос дан ответ. В любом случае, я добавляю свой текущий код, так как он был запрошен. Спасибо всем за обсуждение! новый вопрос здесь! )

Спасибо всем за помощь!Меня попросили перечислить мой код, чтобы предоставить реальный пример того, что я пытаюсь сделать.

Это небольшая, но действительная выдержка из моего кода:

# List 4 servers (for testing)
$servers = Get-QADComputer -sizelimit 4 -WarningAction SilentlyContinue -OSName *server*,*hyper*

# Create list
$serverlistlist = @()

# Loop servers
foreach($server in $servers) {

    # Fetch IP
    $ipaddress = [System.Net.Dns]::GetHostAddresses($Server.name)| select-object IPAddressToString -expandproperty IPAddressToString

    # Gather OSName through WMI
    $OSName = (Get-WmiObject Win32_OperatingSystem -ComputerName $server.name ).caption

    # Ping the server
    if (Test-Connection -ComputerName $server.name -count 1 -Quiet ) {
        $reachable = "Yes"
    }

    # Save info about server
    $serverInfo = New-Object -TypeName PSObject -Property @{
        SystemName = ($server.name).ToLower()
        IPAddress = $IPAddress
        OSName = $OSName
    }
    $serverlistlist += $serverinfo | Select-Object SystemName,IPAddress,OSName
}

Примечания: Я выводлю $ serverlist в csv-файл в конце скрипта. Я перечисляю серверы aprox 500 в своем полном скрипте.

Ответы [ 3 ]

3 голосов
/ 07 марта 2012

Я бы порекомендовал написать функцию, которая обрабатывает все проверки вашего сервера (ping, WMI и т. Д.), А затем обернуть это командой Start-Job.Чтобы избежать перегрузки ресурсов вашего сервера, я бы предложил использовать своего рода «менеджер заданий» вокруг вашей задачи.

foreach ($Server in $ServerList) {
    while ((Get-Job -State Running).Count -ge 20) {
       Start-Sleep -Seconds 5;
    }
    # Start-Job here
}
1 голос
/ 07 марта 2012

Рассматривали ли вы пинг только при сбое вашего первого wmi-запроса? Если сбои редки, то это должно исключить эту часть нагрузки из картинки "

Пинг послужит вашим первым шагом в устранении неполадок, из-за которых не удалось выполнить запрос wmi.

Я бы совмещал это с тем, чтобы запускать несколько параллельных заданий.

Как именно вы пингуете? Можете ли вы поделиться этим фрагментом кода? Там тоже могут быть оптимизации.

0 голосов
/ 23 июля 2016

test connect и ping всегда медленные, у меня похожий скрипт. получает все серверы в домене и собирает статистические данные от каждого, proc util, ram util, free диска, все статистические данные и т. д.

Я нашел функцию тестового порта, не могу вспомнить, где я ее нашел, но тест порта занимает всего около 0,3 секунды, затем я запускаю тестовое соединение, если оно прошло успешно.

Для всех серверов тестовый порт 135, для тестового порта DC 389

function Verify_SinglePort{  ## returns True or false - avoids local host
Param ($CPUNAME, $port)
# This works no matter in which form we get $host - host name or ip address
If($ScriptMachineFQDN -eq $CPUNAME){ 
    ## not a good idea to test a port to and from the same machine
    return $true
}
try {
    $ip = [System.Net.Dns]::GetHostAddresses($CPUNAME) | select-object IPAddressToString -expandproperty  IPAddressToString
    if($ip.GetType().Name -eq "Object[]")
    {
        #If we have several ip's for that address, let's take first one
        $ip = $ip[0]
    }
} catch {
    #Write-Host "Possibly $CPUNAME is wrong host name or IP"
    return $false
}
$t = New-Object Net.Sockets.TcpClient
# We use Try\Catch to remove exception info from console if we can't connect
try
{
    $t.Connect($ip,$port)
} catch {}
if($t.Connected)
{
    $t.Close()
    $msg = "Port $port is operational"
    return $true
}
else
{
    $msg = "Port $port on $ip is closed, "
    $msg += "You may need to contact your IT team to open it. "  
    return $false
}
#Write-Host $msg

}

...