系統城裝機大師 - 唯一官網:www.farandoo.com!

當前位置:首頁 > 腳本中心 > PowerShell > 詳細頁面

PowerShell中Job相關命令及并行執行任務詳解

時間:2020-01-28來源:電腦系統城作者:電腦系統城

前言

在 PowerShell 中可以輕松的執行后臺任務并且讓多個后臺任務并行執行。本文介紹 PowerShell 中 Job 相關的一些命令,并通過 demo 演示如何在后臺同時執行多個任務。下面話不多說了,來一起看看詳細的介紹吧。

PowerShell 中執行后臺任務的模式

下圖描述了在 PowerShell 中執行后臺任務的進程模型(此圖來自互聯網):

首先我們需要一個 PowerShell 進程執行與用戶交互的命令,比如執行 Start-Job 命令運行一個后臺任務。每一個這樣的后臺任務都會在一個新啟動的 PowerShell 進程中執行。所以,如果我們同時啟動三個后臺任務,那么一共有四個 PowerShell 進程在同時運行。

Job 相關的命令

Start-Job 命令會啟動一個運行在后臺的任務。注意,每通過 Start-Job 命令運行一個任務都會創建一個單獨的 PowerShell 進程。

Stop-Job 命令用來停止一個正在運行的后臺任務(由 Start-Job 啟動的任務)。

Get-Job 命令用來獲得當前 session 中的后臺任務對象。

Wait-Job 命令阻塞當前的執行流程,等待指定的后臺任務執行結束。

Receive-Job 命令用來獲得后臺執行任務的執行結果。比如在一個后臺任務結束時,可以通過 Receive-Job 來得到結果,并輸出任務執行時的 output。

Remove-Job 命令刪除當前 session 中的已經完成的任務。當一個任務運行結束后,它并不會被自動刪除,除非你調用 Remove-Job 命令進行刪除,或者是關閉這個 session。如果使用 Remove-Job 刪除一個正在運行的任務,命令會運行失敗。此時需要先使用 Stop-Job 命令先停止任務,然后再用 Remove-Job 進行刪除。

在后臺執行任務

如果只是啟動一個后臺執行的任務,不需要知道任務執行的結果,也不關心任務何時執行結束,那么僅僅使用 Start-Job 命令啟動任務的執行就可以了:


 
  1. > Start-Job -ScriptBlock { sleep 5 }

啟動單個任務并等待任務結束

多數情況下我們是需要知道任務的結束時間的,此時可以通過 Wait-Job 命令阻塞執行流程,直到等待的任務結束:


 
  1. > Start-Job -ScriptBlock { sleep 5; Write-Host "Hello world."; } | Wait-Job

注意:上面的內容是由 Wait-Job 命令輸出的,當時任務的狀態為 "Completed"。

更進一步,我們還想要獲得任務執行過程中的輸出。這時我們就需要用到 Receive-Job 命令。你可以在任務啟動后的任何時刻執行 Receive-Job 命令,但是如果想要得到完整的輸出,就需要在任務結束后調用,此時需要配合 Wait-Job 命令一起使用:


 
  1. $job = Start-Job -ScriptBlock { sleep 5; Write-Host "Hello world."; }
  2. Wait-Job $job
  3. Receive-Job -Job $job

把上面的代碼保存到文件 mytask.ps1 中執行:

Receive-Job 命令輸出了我們在后臺執行的任務的 output。

在后臺執行多個任務并等待結束

因為 Start-Job 命令是非阻塞的,所以理論上我們可以執行任意多次從而啟動很多的后臺任務。和等待單個任務相同,仍然可以使用 Wait-Job 命令來等待所有的任務結束,不過此時需要配合 Get-Job 命令一起使用:


 
  1. > Get-Job | Wait-Job

更常用的方式是我們在 while 循環中不斷的檢查任務的狀態,當所有任務的狀態都是 "Completed" 時表示全部任務執行結束:


 
  1. Remove-Job *
  2. #測試計時開始
  3. $start_time = (Get-Date)
  4. Start-Job -ScriptBlock { sleep 9; Write-Host "Hello myJob1."; } -Name "myJob1"
  5. Start-Job -ScriptBlock { sleep 5; Write-Host "Hello myJob2."; } -Name "myJob2"
  6. $taskCount = 2
  7. while($taskCount -gt 0)
  8. {
  9. foreach($job in Get-Job)
  10. {
  11. $state = [string]$job.State
  12. if($state -eq "Completed")
  13. {
  14. Write-Host($job.Name + " 已經完成")
  15. Receive-Job $job
  16. $taskCount--
  17. Remove-Job $job
  18. }
  19. }
  20. sleep 1
  21. }
  22. "所有任務已完成"
  23. #得出任務運行的時間
  24. (New-TimeSpan $start_time).totalseconds

把上面的代碼保存到 mytask.ps1 文件中并執行:

代碼中我們給每個任務起了名字,并在 while 循環中不斷的使用 Get-Job 命令檢查任務當前的狀態,如果發現任務的狀態為 "Completed",就通過 Remove-Job 命令刪除它,并在刪除前打印任務的名稱和 output。

封裝一個執行后臺任務的函數

下面我們用封裝一個簡單的函數來并行執行多個任務:


 
  1. function Run-Tasks
  2. {
  3. Param
  4. (
  5. $taskArr,
  6. $parallelcount=1
  7. )
  8. #測試計時開始
  9. $startTime = (Get-Date)
  10. #移除本次會話中已有的所有后臺任務
  11. Remove-Job *
  12. # 使用變量 $taskCount 保存還沒有執行完成的任務數
  13. $taskCount = $taskArr.Length
  14.  
  15. #判斷設定的并行任務數是否超過當前任務隊列中的任務數
  16. if($parallelCount -gt $taskArr.Length)
  17. {
  18. $parallelCount = $taskArr.Length
  19. }
  20. #啟動初始任務
  21. foreach($i in 1..$parallelCount)
  22. {
  23. Start-Job $taskArr[$i - 1] -Name "task$i"
  24. }
  25. #初始任務完成后開始的任務
  26. $nextIndex = $parallelCount
  27. #當任務隊列中還有任務時不斷輪詢已建立的任務,當一個后臺任務結束時刪除這個任務,
  28. #然后從任務隊列中取出下一個任務進行執行,然后等待所有任務執行完成。
  29. while(($nextIndex -lt $taskArr.Length) -or ($taskCount -gt 0))
  30. {
  31. foreach($job in Get-Job)
  32. {
  33. $state = [string]$job.State
  34. if($state -eq "Completed")
  35. {
  36. Write-Host($job.Name + " 已經完成,結果如下:")
  37. Receive-Job $job
  38. Remove-Job $job
  39. $taskCount--
  40. if($nextIndex -lt $taskArr.Length)
  41. {
  42. $taskNumber = $nextIndex + 1
  43. Start-Job $taskArr[$nextIndex] -Name "task$taskNumber"
  44. $nextIndex++
  45. }
  46. }
  47. }
  48. sleep 1
  49. }
  50. "所有任務已完成"
  51. #得出任務運行的時間
  52. (New-TimeSpan $startTime).totalseconds
  53. }

上面的函數會在后臺執行用戶的任務,然后等待所有的任務執行結束。并且用戶可以指定同時執行的任務的個數,在任務執行完成后,輸出任務的 output。接下來讓我們嘗試使用這個函數執行一些任務:


 
  1. #定義 6 個任務
  2. $task1 = {sleep 12; Write-Host "Hello myJob1."; }
  3. $task2 = {sleep 5; Write-Host "Hello myJob2."; }
  4. $task3 = {sleep 8; Write-Host "Hello myJob3."; }
  5. $task4 = {sleep 3; Write-Host "Hello myJob4."; }
  6. $task5 = {sleep 20; Write-Host "Hello myJob5."; }
  7. $task6 = {sleep 15; Write-Host "Hello myJob6."; }
  8. #將 6 個任務寫入到一個數組中作為任務隊列
  9. $taskArr = $task1, $task2, $task3, $task4, $task5, $task6
  10. #運行數組中的任務,允許同時運行 4 個任務
  11. Run-Tasks -taskArr $taskArr -parallelcount 4

下面是運行的結果:

總結

能夠隨心所欲的在后臺執行任務是一件感覺非常棒的事情!當然,對于工作來說你能夠把事情做得又快又好(又好可不敢說)。本文只是提供了一個簡單的運行并行任務的 demo,省略了異常處理等重要內容,但這已經足夠您開始 PowerShell 并行任務之旅了。

參考:

分享到:

相關信息

  • Powershell 腳本數字簽名實現方法

    腳本很容易被冒名頂替或者更改,因為它們是由純文本構成的。數字簽名為腳本提供了更高的安全性,因為它能確定腳本和腳本的編輯者的唯一性,并且不能被更改。作為腳本的發布者,你能確定你的腳本沒有被惡意篡改。即使專家也無...

    2020-01-28

  • PowerShell 語音計算器實現代碼

    帶中文發音功能的計算器程序,支持鼠標和小鍵盤輸入,支持多種數值轉人民幣的相關資料...

    2020-01-28

系統教程欄目

欄目熱門教程

人氣教程排行

站長推薦

熱門系統下載

jlzzjlzz亚洲乱熟在线播放