about_Jobs
简短说明
提供有关 PowerShell 后台作业如何在后台运行命令或表达式而不与当前会话交互的信息。
长说明
PowerShell 通过作业同时运行命令和脚本。 PowerShell 提供了三种类型的作业来支持并发。
RemoteJob
- 命令和脚本在远程会话上运行。 有关信息,请参阅 about_Remote_Jobs。BackgroundJob
- 命令和脚本在本地计算机上的单独进程中运行。PSTaskJob
或ThreadJob
- 命令和脚本在本地计算机上同一进程中的单独线程中运行。 有关详细信息,请参阅 about_Thread_Jobs。
在单独的计算机或单独的进程中远程运行脚本可很好地实现隔离。 远程作业中发生的任何错误都不会影响其他正在运行的作业或启动作业的父会话。 但是,远程处理层会增加开销,包括对象序列化。 所有对象在父会话和远程(作业)会话之间传递时会进行序列化和反序列化。 大型复杂数据对象的序列化可能会消耗大量的计算和内存资源,并跨网络传输大量数据。
基于线程的作业不像远程作业和后台作业那样可靠,因为它们在不同线程的同一进程中运行。 如果一个作业发生严重错误,导致进程崩溃,则进程中的所有其他作业都会终止。
但是,基于线程的作业开销更少。 它们不使用远程层或序列化。 结果对象作为对当前会话中的实时对象的引用返回。 基于线程的作业没有这项开销,因此运行速度更快,使用的资源比其他作业类型更少。
重要
创建作业的父会话还会监视作业状态并收集管道数据。 作业子进程在作业达到完成状态后由父进程终止。 如果父会话终止,则所有正在运行的子作业将连同其子进程一起终止。
可通过两种方法应对此情况:
- 使用
Invoke-Command
创建在断开连接的会话中运行的作业。 有关详细信息,请参阅 about_Remote_Jobs。 - 使用
Start-Process
创建新进程而不是作业。 有关详细信息,请参阅 Start-Process。
作业 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 &
获取作业对象
Get-Job
cmdlet 返回表示在当前会话中启动的后台作业的对象。 如果没有参数,Get-Job
返回当前会话中启动的所有作业。
Get-Job
作业对象包含作业的状态,该状态指示作业是否已完成。 已完成作业的状态为 Complete 或 Failed。 作业也可能为 Blocked 或 Running。
Id Name PSJobTypeName State HasMoreData Location Command
-- ---- ------------- ----- ----------- -------- -------
1 Job1 BackgroundJob Complete True localhost Get-Process
可以将作业对象保存在变量中,并将其用于在后面的命令中表示作业。 以下命令获取 ID 为 1 的作业,并将其保存在 $job
变量中。
$job = Get-Job -Id 1
获取作业的结果
运行后台作业时,结果不会立即显示。 若要获取后台作业的结果,请使用 Receive-Job
cmdlet。
以下示例 Receive-Job
cmdlet 使用 $job
变量中的作业对象获取作业的结果。
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
获取和保留部分作业结果
Receive-Job
cmdlet 获取后台作业的结果。 如果作业已完成,则 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
结果显示在表中。 作业的状态显示在 State 列中。
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 属性显示作业 2 仍在运行。 如果要使用 Receive-Job
cmdlet 立即获取作业结果,则结果将不完整。 可以重复使用 Receive-Job
cmdlet 来获取所有结果。 使用 State 属性来确定作业何时完成。
还可以使用 Receive-Job
cmdlet 的 Wait 参数。 使用此参数时,cmdlet 不会返回命令提示符,直到作业完成并且所有结果都可用。
还可以使用 Wait-Job
cmdlet 等待作业的任何或所有结果。 Wait-Job
允许你等待一个或多个特定作业或所有作业。
以下命令使用 Wait-Job
cmdlet 等待 ID 为 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 属性包含以下消息:
连接到远程服务器失败,出现以下错误消息:“访问被拒绝”。