关于作业About Jobs

简短说明Short description

提供有关 PowerShell 后台作业如何在后台运行命令或表达式,而不与当前会话交互的信息。Provides information about how PowerShell background jobs run a command or expression in the background without interacting with the current session.

长说明Long description

PowerShell 通过作业并发运行命令和脚本。PowerShell concurrently runs commands and scripts through jobs. PowerShell 提供三种作业类型来支持并发。There are three jobs types provided by PowerShell to support concurrency.

  • RemoteJob -命令和脚本在远程会话上运行。RemoteJob - Commands and scripts run on a remote session. 有关信息,请参阅 about_Remote_JobsFor information, see about_Remote_Jobs.
  • BackgroundJob -命令和脚本在本地计算机上的单独进程中运行。BackgroundJob - Commands and scripts run in a separate process on the local machine.
  • PSTaskJobThreadJob -命令和脚本在本地计算机上的同一进程内的单独线程中运行。PSTaskJob or ThreadJob - Commands and scripts run in a separate thread within the same process on the local machine. 有关详细信息,请参阅 about_Thread_JobsFor more information, see about_Thread_Jobs.

在单独的计算机上或在单独的进程中远程运行脚本可提供强大的隔离。Running scripts remotely, on a separate machine or in a separate process, provides great isolation. 远程作业中发生的任何错误都不会影响其他正在运行的作业或启动作业的父会话。Any errors that occur in the remote job do not affect other running jobs or the parent session that started the job. 但是,远程处理层增加了开销,包括对象序列化。However, the remoting layer adds overhead, including object serialization. 所有对象都将进行序列化和反序列化,因为在父会话与远程 (作业) 会话之间传递它们。All objects are serialized and deserialized as they are passed between the parent session and the remote (job) session. 大型复杂数据对象的序列化会消耗大量的计算和内存资源,并跨网络传输大量数据。Serialization of large complex data objects can consume large amounts of compute and memory resources and transfer large amounts of data across the network.

基于线程的作业不像远程和后台作业那样可靠,因为它们在不同线程上的同一进程中运行。Thread-based jobs are not as robust as remote and background jobs, because they run in the same process on different threads. 如果一个作业发生了导致进程崩溃的严重错误,则会终止该进程中的所有其他作业。If one job has a critical error that crashes the process, then all other jobs in the process are terminated.

但是,基于线程的作业需要更少的开销。However, thread-based jobs require less overhead. 它们不使用远程层或序列化。They don't use the remoting layer or serialization. 结果对象作为对当前会话中活动对象的引用返回。The result objects are returned as references to live objects in the current session. 如果没有此开销,基于线程的作业运行速度更快,使用的资源比其他作业类型少。Without this overhead, thread-based jobs run faster and use fewer resources than the other job types.

重要

创建作业的父会话还会监视作业状态和收集管道数据。The parent session that created the job also monitors the job status and collects pipeline data. 作业到达完成状态后,父进程终止了作业子进程。The job child process is terminated by the parent process once the job reaches a finished state. 如果终止了父会话,则所有正在运行的子作业都将与其子进程一起终止。If the parent session is terminated, all running child jobs are terminated along with their child processes.

可通过两种方法解决此问题:There are two ways work around this situation:

  1. 用于 Invoke-Command 创建在断开连接的会话中运行的作业。Use Invoke-Command to create jobs that run in disconnected sessions. 有关详细信息,请参阅 about_Remote_JobsFor more information, see about_Remote_Jobs.
  2. 使用 Start-Process 创建新进程,而不是作业。Use Start-Process to create a new process rather than a job. 有关详细信息,请参阅 开始处理For more information, see Start-Process.

作业 cmdletThe job cmdlets

CmdletCmdlet 说明Description
Start-Job 在本地计算机上启动后台作业。Starts a background job on a local computer.
Get-Job 获取在中启动的后台作业Gets the background jobs that were started in the
当前会话。current session.
Receive-Job 获取后台作业的结果。Gets the results of background jobs.
Stop-Job 停止后台作业。Stops a background job.
Wait-Job 禁止显示命令提示符,直到其中一个或所有作业都为Suppresses the command prompt until one or all jobs are
完成.complete.
Remove-Job 删除后台作业。Deletes a background job.
Invoke-Command AsJob 参数在上创建后台作业The AsJob parameter creates a background job on a
远程计算机。remote computer. 你可以使用 Invoke-Command 运行You can use Invoke-Command to run
任何远程作业命令,包括 Start-Jobany job command remotely, including Start-Job.

如何在本地计算机上启动作业How to start a job on the local computer

若要在本地计算机上启动后台作业,请使用 Start-Job cmdlet。To start a background job on the local computer, use the Start-Job cmdlet.

若要编写 Start-Job 命令,请将作业运行的命令括在大括号中, ({}) 。To write a Start-Job command, enclose the command that the job runs in curly braces ({}). 使用 ScriptBlock 参数来指定命令。Use the ScriptBlock parameter to specify the command.

下面的命令启动在 Get-Process 本地计算机上运行命令的后台作业。The following command starts a background job that runs a Get-Process command on the local computer.

Start-Job -ScriptBlock {Get-Process}

启动后台作业时,命令提示符会立即返回,即使作业需要很长时间才能完成。When you start a background job, the command prompt returns immediately, even if the job takes an extended time to complete. 当该作业运行时,你可以继续在此会话中工作而不会发生中断。You can continue to work in the session without interruption while the job runs.

Start-Job命令返回一个表示作业的对象。The Start-Job command returns an object that represents the job. 作业对象包含有关该作业的有用信息,但是不包含作业结果。The job object contains useful information about the job, but it does not contain the job results.

可以将作业对象保存在变量中,然后将其与其他 作业 cmdlet 一起使用来管理后台作业。You can save the job object in a variable and then use it with the other Job cmdlets to manage the background job. 下面的命令启动作业对象并将生成的作业对象保存在 $job 变量中。The following command starts a job object and saves the resulting job object in the $job variable.

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

正在获取作业对象Getting job objects

Get-JobCmdlet 返回对象,这些对象表示在当前会话中启动的后台作业。The Get-Job cmdlet returns objects that represent the background jobs that were started in the current session. 如果没有参数,则 Get-Job 返回在当前会话中启动的所有作业。Without parameters, Get-Job returns all of the jobs that were started in the current session.

Get-Job

作业对象包含作业的状态,该状态指示作业是否已完成。The job object contains the state of the job, which indicates whether the job has finished. 已完成的作业的状态为 " 完成 " 或 " 失败"。A finished job has a state of Complete or Failed. 作业也可能被 阻止正在运行A job might also be Blocked or Running.

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

可以将作业对象保存在变量中,并在后面的命令中使用它来表示作业。You can save the job object in a variable and use it to represent the job in a later command. 以下命令获取 ID 为1的作业,并将其保存在 $job 变量中。The following command gets the job with ID 1 and saves it in the $job variable.

$job = Get-Job -Id 1

获取作业的结果Getting the results of a job

运行后台作业时,结果不会立即显示。When you run a background job, the results do not appear immediately. 若要获取后台作业的结果,请使用 Receive-Job cmdlet。To get the results of a background job, use the Receive-Job cmdlet.

下面的示例 Receive-Job 使用变量中的作业对象获取作业的结果 $jobThe following example, the Receive-Job cmdlet gets the results of the job using job object in the $job variable.

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
...

可以将作业的结果保存在变量中。You can save the results of a job in a variable. 以下命令将变量中的作业结果保存 $job$results 变量中。The following command saves the results of the job in the $job variable to the $results variable.

$results = Receive-Job -Job $job

获取并保留部分作业结果Getting and keeping partial job results

Receive-JobCmdlet 将获取后台作业的结果。The Receive-Job cmdlet gets the results of a background job. 如果作业已完成,则 Receive-Job 获取所有作业结果。If the job is complete, Receive-Job gets all job results. 如果作业仍在运行,将 Receive-Job 获取迄今为止生成的结果。If the job is still running, Receive-Job gets the results that have been generated thus far. 可以再次运行 Receive-Job 命令来获取剩余结果。You can run Receive-Job commands again to get the remaining results.

默认情况下, Receive-Job 会从缓存中删除存储作业结果的结果。By default, Receive-Job deletes the results from the cache where job results are stored. 再次运行时 Receive-Job ,只会获得首次运行后收到的新结果。When you run Receive-Job again, you get only the new results that arrived after the first run.

以下命令显示在 Receive-Job 作业完成之前运行的命令的结果。The following commands show the results of Receive-Job commands run before the job is complete.

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 删除返回的作业结果。Use the Keep parameter to prevent Receive-Job from deleting the job results that are returned. 以下命令显示对尚未完成的作业使用 Keep 参数的效果。The following commands show the effect of using the Keep parameter on a job that is not yet complete.

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

正在等待结果Waiting for the results

如果运行需要很长时间才能完成的命令,则可以使用作业对象的属性来确定作业的完成时间。If you run a command that takes a long time to complete, you can use the properties of the job object to determine when the job is complete. 以下命令使用 Get-Job 对象获取当前会话中的所有后台作业。The following command uses the Get-Job object to get all of the background jobs in the current session.

Get-Job

结果将显示在表中。The results appear in a table. 作业的状态显示在 " 状态 " 列中。The status of the job appears in the State column.

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...

在这种情况下," 状态 " 属性显示 "作业 2" 仍在运行。In this case, the State property reveals that Job 2 is still running. 如果你 Receive-Job 现在使用 cmdlet 来获取作业结果,结果将不完整。If you were to use the Receive-Job cmdlet to get the job results now, the results would be incomplete. 可以重复使用此 Receive-Job cmdlet 来获取所有结果。You can use the Receive-Job cmdlet repeatedly to get all of the results. 使用 State 属性来确定作业的完成时间。Use the State property to determine when the job is complete.

你还可以使用该 cmdlet 的 Wait 参数 Receive-JobYou can also use the Wait parameter of the Receive-Job cmdlet. 如果使用此参数,则在作业完成并且所有结果都可用之前,cmdlet 不会返回命令提示符。When use use this parameter, the cmdlet does not return the command prompt until the job is completed and all results are available.

你还可以使用 Wait-Job cmdlet 等待作业的任何或所有结果。You can also use the Wait-Job cmdlet to wait for any or all of the results of the job. Wait-Job 允许你等待一个或多个特定作业或所有作业。Wait-Job lets you wait for one or more specific job or for all jobs. 以下命令使用 Wait-Job cmdlet 等待 ID 为的作业The following command uses the Wait-Job cmdlet to wait for a job with ID 10.

Wait-Job -ID 10

因此,在作业完成之前,会禁止 PowerShell 提示。As a result, the PowerShell prompt is suppressed until the job is completed.

还可以等待预先确定的时间段。You can also wait for a predetermined period of time. 此命令使用 Timeout 参数将等待时间限制为120秒。This command uses the Timeout parameter to limit the wait to 120 seconds. 当时间到期时,命令提示符会返回,但作业将继续在后台运行。When the time expires, the command prompt returns, but the job continues to run in the background.

Wait-Job -ID 10 -Timeout 120

停止作业Stopping a job

若要停止后台作业,请使用 Stop-Job cmdlet。To stop a background job, use the Stop-Job cmdlet. 下面的命令启动一个作业以获取系统事件日志中的每个条目。The following command starts a job to get every entry in the System event log. 它将作业对象保存在 $job 变量中。It saves the job object in the $job variable.

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

以下命令停止作业。The following command stops the job. 它使用管道运算符 (|) 将变量中的作业发送 $jobStop-JobIt uses a pipeline operator (|) to send the job in the $job variable to Stop-Job.

$job | Stop-Job

删除作业Deleting a job

若要删除后台作业,请使用 Remove-Job cmdlet。To delete a background job, use the Remove-Job cmdlet. 以下命令删除变量中的作业 $jobThe following command deletes the job in the $job variable.

Remove-Job -Job $job

调查失败的作业Investigating a failed job

作业可能会因多种原因而失败。Jobs can fail for many reasons. 作业对象包含 Reason 属性,其中包含有关失败原因的信息。the job object contains a Reason property that contains information about the cause of the failure.

下面的示例启动一个作业,该作业没有所需的凭据。The following example starts a job without the required credentials.

$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:...

检查 原因 属性以找到导致作业失败的错误。Inspect the Reason property to find the error that caused the job to fail.

$job.ChildJobs[0].JobStateInfo.Reason

在这种情况下,作业失败,因为远程计算机需要显式凭据才能运行该命令。In this case, the job failed because the remote computer required explicit credentials to run the command. Reason 属性包含以下消息:The Reason property contains the following message:

连接到远程服务器失败,出现以下错误消息: "访问被拒绝"。Connecting to remote server failed with the following error message: "Access is denied".

另请参阅See also