使用-asjob使脚本​​更高效

时间:2012-03-06 13:35:19

标签: powershell jobs

我有一个aprox 1000行脚本,它遍历AD中的所有服务器。 如果ping = ok,脚本会ping每个服务器并执行一堆WMI查询。 我的脚本将结果存储在哈希表中,我在脚本末尾输出到CSV。 这是有效的,但它是sloooow ..我们正在谈论接近两个小时。我一直在考虑这样做更有效率,我认为-asjob听起来是个好主意。

但我可以将此作为并发作业吗?我的服务器会处理负载吗?是-asjob的方式呢?

在等待我的脚本运行循环时,希望得到一些输入。

修改

我的观点是脚本等待测试连接(ping)返回true或false。我想同时运行多个ping。

编辑2

注意: 我已经开始一个单独的问题,因为我觉得我的原始问题已得到解答。无论如何,我已经包含了我当前的代码。感谢大家投球! new question here!

到目前为止,感谢大家的帮助!我被要求列出我的代码,以提供我想要做的实际例子。

这是我的代码中的一个小而有效的摘录:

# 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 个答案:

答案 0 :(得分:3)

我建议编写一个处理所有服务器验证的函数(ping,WMI等),然后将其包装在Start-Job命令中。为了避免服务器资源过载,我建议围绕你的任务包装某种“工作经理”。

foreach ($Server in $ServerList) {
    while ((Get-Job -State Running).Count -ge 20) {
       Start-Sleep -Seconds 5;
    }
    # Start-Job here
}

答案 1 :(得分:1)

您是否考虑过仅在第一次wmi请求失败时才进行ping操作?如果失败很少,那么这应该从图片“

中删除这一部分工作量

ping将作为解决wmi请求失败原因的第一步。

我会将此与开始多个并发作业相结合。

你究竟在打什么?你能分享那段代码吗?那里也可能有优化。

答案 2 :(得分:0)

测试连接和ping总是慢,我有一个类似的脚本。获取域中的所有服务器,并从每个服务器收集统计数据,proc util,ram util,disk free,所有nic统计数据等

我发现了一个测试端口功能,无法记住我发现它的位置,但端口测试只有大约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

}