PowerShell 多執行緒的使用

2021-09-04 07:02:15 字數 2505 閱讀 4551

今天乙個朋友問我在powershell裡面如何能夠併發的ping上萬台機器?預設的test-connection 儘管有-computer這個引數,他的方式是按順序的挨個ping,全部跑下來可能有好幾個小時。

比如我需要花18秒的時間才能ping完40臺伺服器,如果成千上萬的話就很費時間了。

這之前,豆子對多執行緒的使用僅僅限於了解invoke-command可以同時對30個物件操作,經過一番學習,終於發現還有其他 的高階方式。

powershell裡面,對於多執行緒的使用大概是兩大方式。

第乙個是建立多個後台的job。這種方式通過start-job或者 -asjob建立後台job,然後通過get-job獲取當前的任務,通過receive-job來獲取完成任務的結果,最後還得remove-job來釋放記憶體。缺點是效能不高,尤其在建立job和退出job的過程中會消耗大量時間和資源。

第二個方式是建立多個runspace,這個工作原理和invoke-command一樣,每乙個遠端的session繫結乙個runspace。我們可以建立乙個runspace pool,指定在這個資源池裡面最多可以同時執行多少個runspace。

比起第一種方式,runspace的效能強悍了太多。下面有人做的對比實驗,可以看見幾乎是幾十倍的效能差距。

現在看看怎麼來實現。豆子主要參考了這篇部落格的方法和原理,寫了乙個簡單的指令碼來。 

思路很簡單,建立runspace pool,指定runspace的數量,然後對要測試的物件集合,對每乙個物件都建立乙個後台的runspace job,繫結要執行的指令碼,傳入引數,把結果儲存在ps物件或者hash表中,最後等待所有job結束,輸出結果。

$throttle = 20 #threads

#指令碼塊,對指定的計算機傳送乙個icmp包測試,結果儲存在乙個物件裡面

$scriptblock = 

return $runresult

}#建立乙個資源池,指定多少個runspace可以同時執行

$runspacepool = [runspacefactory]::createrunspacepool(1, $throttle)

$runspacepool.open()

$jobs = @()

#獲取windows 2012伺服器的資訊,對每乙個伺服器單獨建立乙個job,該job執行icmp的測試,並把結果儲存在乙個ps物件中

(get-adcomputer -filter ).name | % } 

#迴圈輸出等待的資訊.... 直到所有的job都完成 

write-host "waiting.." -nonewline

do  while ( $jobs.result.iscompleted -contains $false)

write-host "all jobs completed!"

#輸出結果 

$results = @()

foreach ($job in $jobs)

$results

大概5秒之後 結果就出來了。 如果有興趣的話可以使用measure-command命令來測試不同執行緒數的效果,根據我的測試,30個程序同時執行只需4秒出結果,而2個同時執行大概需要9秒才能出結果。

知道原理之後就可以進一步優化和抽象化指令碼。這一點已經有人做好了。

依葫蘆畫瓢,我想通過他來呼叫test-connection也是成功的

再比如我ping 乙個ip範圍的計算機

python 多執行緒threading的使用

一 執行緒建立方法 1.普通建立 import threading defrun name for i in range 3 print name if name main t1 threading.thread target run,args t1 t2 threading.thread targ...

python多執行緒threading的使用

一 執行緒建立方法 1.普通建立 import threadingdef run name for i in range 3 print name if name main t1 threading.thread target run,args t1 t2 threading.thread targ...

Python多執行緒threading的使用

一.threading的引數傳遞,引數之後的 不能少,此處的 是用來區分此引數作為元組 包含多個引數 來傳遞的,而不是單個引數傳遞 coding utf 8 import threading import time def b arg time.sleep 2 print i m b print i...