關於工作

簡短描述

提供 PowerShell 背景工作如何在背景中執行命令或運算式,而不需與目前會話互動的資訊。

完整描述

PowerShell 會透過作業同時執行命令和腳本。 PowerShell 提供三種作業類型來支援並行。

  • RemoteJob - 在遠端會話上執行的命令和腳本。 如需詳細資訊,請參閱 about_Remote_Jobs
  • BackgroundJob - 命令和腳本會在本機電腦上的個別進程中執行。
  • PSTaskJobThreadJob - 命令和腳本會在本機電腦上相同進程的個別執行緒中執行。 如需詳細資訊,請參閱 about_Thread_Jobs

從遠端執行腳本,可在個別的電腦上或在個別進程中執行腳本,可提供絕佳的隔離。 遠端作業中發生的任何錯誤都不會影響其他執行中作業或啟動作業的父會話。 不過,遠端層會增加額外負荷,包括物件序列化。 所有物件都會序列化和還原序列化,因為它們會在父會話與遠端 (作業) 會話之間傳遞。 序列化大型複雜資料物件可能會耗用大量的計算和記憶體資源,並透過網路傳輸大量資料。

執行緒型作業不如遠端和背景工作強固,因為它們在不同的執行緒上在同一個進程中執行。 如果某個作業發生損毀進程的重大錯誤,則處理常式中的所有其他作業都會終止。

不過,執行緒型作業需要較少的額外負荷。 它們不會使用遠端層或序列化。 結果物件會當做目前會話中即時物件的參考傳回。 如果沒有此額外負荷,執行緒型作業的執行速度會比其他作業類型更快,並使用較少的資源。

重要

建立作業的父會話也會監視作業狀態並收集管線資料。 作業子進程會在作業達到完成狀態之後,由父進程終止。 如果父會話終止,所有執行中的子作業都會隨著其子進程一起終止。

有兩種方式可以解決此限制:

  1. 用來 Invoke-Command 建立在中斷連線會話中執行的作業。 如需詳細資訊,請參閱 about_Remote_Jobs
  2. 使用 Start-Process 來建立新的進程,而不是作業。 如需詳細資訊,請參閱 Start-Process

作業 Cmdlet

Cmdlet 描述
Start-Job 在本機電腦上啟動背景工作。
Get-Job 取得 在 中啟動的背景工作
目前的會話。
Receive-Job 取得背景工作的結果。
Stop-Job 停止背景工作。
Wait-Job 隱藏命令提示字元,直到一或所有作業都處於
完成。
Remove-Job 移除背景工作。
Invoke-Command AsJob參數會在 上建立背景工作
遠端電腦。 您可以使用 Invoke-Command 來執行
遠端的任何作業命令,包括 Start-Job

如何在本機電腦上啟動作業

若要在本機電腦上啟動背景工作,請使用 Start-Job Cmdlet。

若要撰寫 Start-Job 命令,請將作業執行的命令括在大括弧 ({}) 。 使用 ScriptBlock 參數來指定 命令。

下列命令會啟動在本機電腦上執行 Get-Process 命令的背景作業。

Start-Job -ScriptBlock {Get-Process}

當您啟動背景作業時,即使作業需要較長的時間才能完成,命令提示字元也會立即傳回。 工作執行時,您可以在工作階段中繼續工作,而不需中斷。

命令會 Start-Job 傳回代表作業的物件。 工作物件包含工作的相關實用資訊,但是不包含工作結果。

您可以將工作物件儲存在變數中,然後將其與其他 作業 Cmdlet 搭配使用,以管理背景工作。 下列命令會啟動工作物件,並將產生的工作物件儲存在 變數中 $job

$job = Start-Job -ScriptBlock {Get-Process}

從 PowerShell 6.0 開始,您可以使用管線結尾 (背景 & 運算子) 來啟動背景作業。 如需詳細資訊,請參閱 背景運算子

使用背景運算子的功能相當於使用 Start-Job 上一個範例中的 Cmdlet。

$job = Get-Process &

取得工作物件

Cmdlet 會 Get-Job 傳回物件,這些物件代表在目前會話中啟動的背景工作。 如果沒有參數, Get-Job 則會傳回在目前會話中啟動的所有作業。

Get-Job

工作物件包含作業的狀態,指出作業是否已完成。 已完成的作業狀態為 [完成 ] 或 [ 失敗]。 作業也可能是 [封鎖 ] 或 [ 執行中]。

Id  Name  PSJobTypeName State      HasMoreData  Location   Command
--  ----  ------------- -----      -----------  --------   -------
1   Job1  BackgroundJob Complete   True         localhost  Get-Process

您可以將工作物件儲存在變數中,並在稍後的命令中使用它來表示作業。 下列命令會取得識別碼為 1 的作業,並將它儲存在 變數中 $job

$job = Get-Job -Id 1

取得作業的結果

當您執行背景工作時,結果不會立即出現。 若要取得背景工作的結果,請使用 Receive-Job Cmdlet。

下列範例會 Receive-Job 使用 變數中的 $job 工作物件,Cmdlet 取得作業的結果。

Receive-Job -Job $job
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)    Id ProcessName
-------  ------    -----      ----- -----   ------    -- -----------
    103       4    11328       9692    56           1176 audiodg
    804      14    12228      14108   100   101.74  1740 CcmExec
    668       7     2672       6168   104    32.26   488 csrss
...

您可以將作業的結果儲存在變數中。 下列命令會將變數中 $job 作業的結果儲存至 $results 變數。

$results = Receive-Job -Job $job

取得和保留部分作業結果

Cmdlet Receive-Job 會取得背景工作的結果。 如果作業已完成, Receive-Job 則取得所有作業結果。 如果作業仍在執行中, Receive-Job 則取得到目前為止產生的結果。 您可以再次執行 Receive-Job 命令,以取得其餘的結果。

根據預設, Receive-Job 會從儲存作業結果的快取中刪除結果。 當您再次執行 Receive-Job 時,只會取得第一次執行之後抵達的新結果。

下列命令會顯示在作業完成之前執行的命令結果 Receive-Job

C:\PS> Receive-Job -Job $job

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    103       4    11328       9692    56            1176 audiodg
    804      14    12228      14108   100   101.74   1740 CcmExec

C:\PS> Receive-Job -Job $job

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    68       3     2632        664    29     0.36   1388 ccmsetup
   749      22    21468      19940   203   122.13   3644 communicator
   905       7     2980       2628    34   197.97    424 csrss
  1121      25    28408      32940   174   430.14   3048 explorer

使用 Keep 參數可防止 Receive-Job 刪除傳回的作業結果。 下列命令會顯示在尚未完成之作業上使用 Keep 參數的效果。

C:\PS> Receive-Job -Job $job -Keep

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    103       4    11328       9692    56            1176 audiodg
    804      14    12228      14108   100   101.74   1740 CcmExec

C:\PS> Receive-Job -Job $job -Keep

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    103       4    11328       9692    56            1176 audiodg
    804      14    12228      14108   100   101.74   1740 CcmExec
     68       3     2632        664    29     0.36   1388 ccmsetup
    749      22    21468      19940   203   122.13   3644 communicator
    905       7     2980       2628    34   197.97    424 csrss
   1121      25    28408      32940   174   430.14   3048 explorer

等候結果

如果您執行需要很長的時間才能完成的命令,您可以使用工作物件的屬性來判斷作業何時完成。 下列命令會 Get-Job 使用 物件來取得目前會話中的所有背景工作。

Get-Job

結果會出現在資料表中。 作業的狀態會出現在 [ 狀態 ] 資料行中。

Id Name  PSJobTypeName State    HasMoreData Location  Command
-- ----  ------------- -----    ----------- --------  -------
1  Job1  BackgroundJob Complete True        localhost Get-Process
2  Job2  BackgroundJob Running  True        localhost Get-EventLog -Log ...
3  Job3  BackgroundJob Complete True        localhost dir -Path C:\* -Re...

在此情況下, State 屬性會顯示 Job 2 仍在執行中。 如果您要使用 Receive-Job Cmdlet 立即取得作業結果,則結果會不完整。 您可以重複使用 Receive-Job Cmdlet 來取得所有結果。 使用 State 屬性來判斷作業何時完成。

您也可以使用 Cmdlet 的 Receive-JobWait參數。 使用此參數時,Cmdlet 不會傳回命令提示字元,直到作業完成且所有結果都可供使用為止。

您也可以使用 Wait-Job Cmdlet 來等候作業的任何或所有結果。 Wait-Job 可讓您等候一或多個特定作業或所有作業。 下列命令會 Wait-Job 使用 Cmdlet 來 等候識別碼為 10 的作業。

Wait-Job -ID 10

因此,PowerShell 提示字元會隱藏,直到作業完成為止。

您也可以等候預先決定的時間。 此命令會使用 Timeout 參數來限制等候 120 秒。 當時間到期時,命令提示字元會傳回,但作業會繼續在背景中執行。

Wait-Job -ID 10 -Timeout 120

停止作業

若要停止背景工作,請使用 Stop-Job Cmdlet。 下列命令會啟動作業,以取得系統事件記錄檔中的每個專案。 它會將工作物件儲存在 變數中 $job

$job = Start-Job -ScriptBlock {Get-EventLog -Log System}

下列命令會停止作業。 它會使用管線運算子 (|) 將變數中的 $job 作業傳送至 Stop-Job

$job | Stop-Job

刪除作業

若要移除背景工作,請使用 Remove-Job Cmdlet。 下列命令會刪除 變數中的 $job 作業。

Remove-Job -Job $job

調查失敗的工作

作業可能會因為許多原因而失敗。 工作物件包含 Reason 屬性,其中包含失敗原因的相關資訊。

下列範例會啟動沒有必要認證的作業。

$job = Start-Job -ScriptBlock {New-Item -Path HKLM:\Software\MyCompany}
Get-Job $job

Id Name  PSJobTypeName State  HasMoreData  Location  Command
-- ----  ------------- -----  -----------  --------  -------
1  Job1  BackgroundJob Failed False        localhost New-Item -Path HKLM:...

檢查 Reason 屬性,找出導致作業失敗的錯誤。

$job.ChildJobs[0].JobStateInfo.Reason

在此情況下,作業失敗,因為遠端電腦需要明確的認證才能執行命令。 Reason屬性包含下列訊息:

連線到遠端伺服器失敗,並出現下列錯誤訊息:「拒絕存取」。

另請參閱