今天一個朋友問我在Powershell里面如何能夠并發(fā)的ping上萬臺機器?默認的test-connection 盡管有-computer這個參數(shù),他的方式是按順序的挨個ping,全部跑下來可能有好幾個小時。
我們一直強調(diào)網(wǎng)站設(shè)計制作、成都網(wǎng)站設(shè)計對于企業(yè)的重要性,如果您也覺得重要,那么就需要我們慎重對待,選擇一個安全靠譜的網(wǎng)站建設(shè)公司,企業(yè)網(wǎng)站我們建議是要么不做,要么就做好,讓網(wǎng)站能真正成為企業(yè)發(fā)展過程中的有力推手。專業(yè)網(wǎng)站設(shè)計公司不一定是大公司,創(chuàng)新互聯(lián)作為專業(yè)的網(wǎng)絡(luò)公司選擇我們就是放心。比如我需要花18秒的時間才能ping完40臺服務(wù)器,如果成千上萬的話就很費時間了。
measure-commnd -expression { $computers=Get-ADComputer -Filter {operatingsystem -like "*2012*"} Test-Connection -ComputerName $computers.name -Count 1 }
這之前,豆子對多線程的使用僅僅限于了解invoke-command可以同時對30個對象操作,經(jīng)過一番學(xué)習(xí),終于發(fā)現(xiàn)還有其他 的高級方式。
PowerShell里面,對于多線程的使用大概是兩大方式。
第一個是創(chuàng)建多個后臺的job。這種方式通過start-job或者 -asjob創(chuàng)建后臺job,然后通過get-job獲取當(dāng)前的任務(wù),通過receive-job來獲取完成任務(wù)的結(jié)果,最后還得remove-job來釋放內(nèi)存。缺點是性能不高,尤其在創(chuàng)建job和退出job的過程中會消耗大量時間和資源。
第二個方式是創(chuàng)建多個runspace,這個工作原理和invoke-command一樣,每一個遠程的session綁定一個runspace。我們可以創(chuàng)建一個runspace pool,指定在這個資源池里面最多可以同時執(zhí)行多少個runspace。
比起第一種方式,runspace的性能強悍了太多。下面有人做的對比實驗,可以看見幾乎是幾十倍的性能差距。
http://learn-powershell.net/2012/05/13/using-background-runspaces-instead-of-psjobs-for-better-performance/
現(xiàn)在看看怎么來實現(xiàn)。豆子主要參考了這篇博客的方法和原理,寫了一個簡單的腳本來。
http://thesurlyadmin.com/2013/02/11/multithreading-powershell-scripts/
思路很簡單,創(chuàng)建runspace pool,指定runspace的數(shù)量,然后對要測試的對象集合,對每一個對象都創(chuàng)建一個后臺的runspace job,綁定要執(zhí)行的腳本,傳入?yún)?shù),把結(jié)果保存在ps對象或者hash表中,最后等待所有job結(jié)束,輸出結(jié)果。
$Throttle = 20 #threads #腳本塊,對指定的計算機發(fā)送一個ICMP包測試,結(jié)果保存在一個對象里面 $ScriptBlock = { Param ( [string]$Computer ) $a=test-connection -ComputerName $Computer -Count 1 $RunResult = New-Object PSObject -Property @{ IPv4Adress=$a.ipv4address.IPAddressToString ComputerName=$Computer } Return $RunResult } #創(chuàng)建一個資源池,指定多少個runspace可以同時執(zhí)行 $RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, $Throttle) $RunspacePool.Open() $Jobs = @() #獲取Windows 2012服務(wù)器的信息,對每一個服務(wù)器單獨創(chuàng)建一個job,該job執(zhí)行ICMP的測試,并把結(jié)果保存在一個PS對象中 (get-adcomputer -filter {operatingsystem -like "*2012*"}).name | % { #Start-Sleep -Seconds 1 $Job = [powershell]::Create().AddScript($ScriptBlock).AddArgument($_) $Job.RunspacePool = $RunspacePool $Jobs += New-Object PSObject -Property @{ Server = $_ Pipe = $Job Result = $Job.BeginInvoke() } } #循環(huán)輸出等待的信息.... 直到所有的job都完成 Write-Host "Waiting.." -NoNewline Do { Write-Host "." -NoNewline Start-Sleep -Seconds 1 } While ( $Jobs.Result.IsCompleted -contains $false) Write-Host "All jobs completed!" #輸出結(jié)果 $Results = @() ForEach ($Job in $Jobs) { $Results += $Job.Pipe.EndInvoke($Job.Result) } $Results
大概5秒之后 結(jié)果就出來了。 如果有興趣的話可以使用measure-command命令來測試不同線程數(shù)的效果,根據(jù)我的測試,30個進程同時執(zhí)行只需4秒出結(jié)果,而2個同時執(zhí)行大概需要9秒才能出結(jié)果。
知道原理之后就可以進一步優(yōu)化和抽象化腳本。這一點已經(jīng)有人做好了。https://github.com/RamblingCookieMonster/Invoke-Parallel/blob/master/Invoke-Parallel/Invoke-Parallel.ps1
下載,Unlock和dot source之后就能直接調(diào)用了。這里提供了一些例子作為參考https://github.com/RamblingCookieMonster/Invoke-Parallel
依葫蘆畫瓢,我想通過他來調(diào)用test-connection也是成功的
get-adcomputer -Filter {operatingsystem -like "*2012*"} | select -ExpandProperty name | Invoke-Parallel -ScriptBlock {Test-Connection -computername $_ -count 1}
再比如我ping 一個IP范圍的計算機
1..254| Invoke-Parallel -ScriptBlock {Test-Connection -ComputerName "10.2.100.$_" -Count 1 -ErrorAction SilentlyContinue -ErrorVariable err | select Ipv4address, @{n='DNS';e={[System.Net.Dns]::gethostentry($_.ipv4address).hostname}}} -Throttle 20
最后,網(wǎng)上也有現(xiàn)成的腳本用來并發(fā)的測試ping,原理也是調(diào)用上面的invoke-parallel函數(shù),不過他還增加了其他的函數(shù)用來測試rdp,winrm,rpc等遠程訪問的端口是否打開,進一步擴充了功能??梢灾苯釉谶@里下載
http://ramblingcookiemonster.github.io/Invoke-Ping/
invoke-ping -ComputerName (Get-ADComputer -Filter {operatingsystem -like "*2012*"}).name -Detail RDP,rpc | ft -Wrap
參考資料:
1. http://learn-powershell.net/2012/05/13/using-background-runspaces-instead-of-psjobs-for-better-performance/
2. https://github.com/RamblingCookieMonster/Invoke-Parallel
3. http://thesurlyadmin.com/2013/02/11/multithreading-powershell-scripts/
4. http://ramblingcookiemonster.github.io/Invoke-Ping/
5. http://learn-powershell.net/2012/05/10/speedy-network-information-query-using-powershell/
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。