关于远程作业

简短说明

介绍如何在远程计算机上运行作业。

详细说明

PowerShell 通过作业并发运行命令和脚本。 PowerShell 提供三种作业类型来支持并发。

  • RemoteJob - 命令和脚本在远程会话中运行。
  • BackgroundJob - 命令和脚本在本地计算机上的单独进程中运行。 有关详细信息,请参阅 about_Jobs
  • PSTaskJobThreadJob - 命令和脚本在本地计算机上的同一进程中的单独线程中运行。 有关详细信息,请参阅 about_Thread_Jobs

在单独的计算机上或在单独的进程中远程运行脚本可提供很好的隔离。 远程作业中发生的任何错误不会影响其他正在运行的作业或启动该作业的父会话。 但是,远程处理层会增加开销,包括对象序列化。 在父会话与远程 (作业) 会话之间传递时,所有对象都会进行序列化和反序列化。 序列化大型复杂数据对象可能会消耗大量的计算和内存资源,并跨网络传输大量数据。

重要

创建作业的父会话还会监视作业状态并收集管道数据。 作业达到完成状态后,父进程将终止作业子进程。 如果终止父会话,则所有正在运行的子作业将连同其子进程一起终止。

有两种方法可以解决此问题:

  1. 使用 Invoke-Command 创建在断开连接的会话中运行的作业。 请参阅本文的 分离进程 部分。
  2. 使用 Start-Process 创建新进程,而不是作业。 有关详细信息,请参阅 Start-Process

远程作业

可以使用三种不同的方法在远程计算机上运行作业。

  • 在远程计算机上启动交互式会话。 然后在交互式会话中启动作业。 尽管所有操作都在远程计算机上执行,但过程与运行本地作业的过程相同。

  • 在远程计算机上运行作业,该作业将结果返回到本地计算机。 如果要收集作业结果并将其维护在本地计算机上的中心位置,请使用此方法。

  • 在远程计算机上运行作业,该作业在远程计算机上维护其结果。 在原始计算机上更安全地维护作业数据时,请使用此方法。

在交互式会话中启动作业

可以使用远程计算机启动交互式会话,然后在交互式会话期间启动作业。 有关交互式会话的详细信息,请参阅 about_Remote 和 。Enter-PSSession

在交互式会话中启动作业的过程与在本地计算机上启动后台作业的过程几乎完全相同。 但是,所有操作都发生在远程计算机上,而不是本地计算机上。

  1. Enter-PSSession使用 cmdlet 启动与远程计算机的交互式会话。 可以使用 的 ComputerName 参数 Enter-PSSession 为交互式会话建立临时连接。 或者,可以使用 Session 参数在 PowerShell 会话中运行交互式会话, (PSSession) 。

    以下命令在 Server01 计算机上启动交互式会话。

    C:\PS> Enter-PSSession -computername Server01
    

    命令提示符将更改为显示你现在已连接到 Server01 计算机。

    Server01\C:>
    
  2. 若要在会话中启动远程作业,请使用 Start-Job cmdlet。 以下命令运行一个远程作业,该作业获取 Server01 计算机上的Windows PowerShell事件日志中的事件。 cmdlet Start-Job 返回表示作业的 对象。

    此命令将作业对象保存在 变量中 $job

    Server01\C:> $job = Start-Job -scriptblock {
      Get-Eventlog "Windows PowerShell"
    }
    

    在作业运行时,可以使用交互式会话来运行其他命令,包括其他作业。 但是,在作业完成之前,必须使交互式会话保持打开状态。 如果结束会话,作业将中断,结果将丢失。

  3. 若要了解作业是否已完成,请显示变量的值 $job ,或使用 Get-Job cmdlet 获取作业。 以下命令使用 Get-Job cmdlet 显示作业。

    Server01\C:> Get-Job $job
    
    SessionId  Name  State      HasMoreData  Location   Command
    ---------  ----  -----      -----------  --------   -------
    1          Job1  Complete   True         localhost  Get-Eventlog "Windows...
    

    输出 Get-Job 显示作业在“localhost”计算机上运行,因为作业已启动,并且运行在同一台计算机 (在本例中为 Server01) 。

  4. 若要获取作业的结果,请使用 Receive-Job cmdlet。 可以在交互式会话中显示结果,也可以将它们保存到远程计算机上的文件中。 以下命令在 $job 变量中获取作业的结果。 该命令使用重定向运算符 (>) 将作业结果保存在 Server01 计算机上的 PsLog.txt 文件中。

    Server01\C:> Receive-Job $job > c:\logs\PsLog.txt
    
  5. 若要结束交互式会话,请使用 Exit-PSSession cmdlet。 命令提示符会更改,显示你已返回本地计算机上的原始会话。

    Server01\C:> Exit-PSSession
    C:\PS>
    
  6. 若要随时在 Server01 计算机上查看文件的内容 PsLog.txt ,请启动另一个交互式会话,或运行远程命令。 这种类型的命令最好在 PSSession 中运行, (持久性连接) ,以防你想要使用多个命令来调查和管理文件中的数据 PsLog.txt 。 有关 PSSession 的详细信息,请参阅 about_PSSessions

    以下命令使用 New-PSSession cmdlet 创建连接到 Server01 计算机的 PSSession ,并使用 Invoke-Command cmdlet 在 PSSession 中运行 Get-Content 命令以查看文件的内容。

    $s = New-PSSession -computername Server01
    Invoke-Command -session $s -scriptblock {
      Get-Content c:\logs\pslog.txt}
    

启动一个远程作业,该作业将结果返回到本地计算机 (AsJob)

若要在将命令结果返回到本地计算机的远程计算机上启动作业,请使用 cmdlet(如 cmdlet)Invoke-CommandAsJob 参数。

使用 AsJob 参数时,作业对象实际上是在本地计算机上创建的,即使作业在远程计算机上运行也是如此。 作业完成后,结果将返回到本地计算机。

可以使用包含作业名词的 cmdlet (作业 cmdlet) 来管理由任何 cmdlet 创建的任何作业。 许多具有 AsJob 参数的 cmdlet 不使用 PowerShell 远程处理,因此甚至可以在未配置远程处理且不符合远程处理要求的计算机上使用它们。

  1. 以下命令使用 的 AsJob 参数 Invoke-Command 在 Server01 计算机上启动作业。 作业运行一个 Get-Eventlog 命令,用于获取系统日志中的事件。 可以使用 JobName 参数为作业分配显示名称。

    Invoke-Command -computername Server01 -scriptblock {
      Get-Eventlog system} -AsJob
    

    命令的结果类似于以下示例输出。

    SessionId   Name   State    HasMoreData   Location   Command
    ---------   ----   -----    -----------   --------   -------
    1           Job1   Running  True          Server01   Get-Eventlog system
    

    使用 AsJob 参数时, Invoke-Command 返回返回的作业对象 Start-Job 类型相同。 可以将作业对象保存在变量中,也可以使用 Get-Job 命令获取作业。

    请注意,Location 属性的值显示作业在 Server01 计算机上运行。

  2. 若要管理使用 cmdlet 的 AsJob 参数启动的 Invoke-Command 作业,请使用作业 cmdlet。 由于表示远程作业的作业对象位于本地计算机上,因此无需运行远程命令来管理作业。

    若要确定作业是否已完成,请使用 Get-Job 命令。 以下命令获取在当前会话中启动的所有作业。

    Get-Job
    

    由于远程作业是在当前会话中启动的,因此本地 Get-Job 命令会获取作业。 作业对象的 State 属性显示命令已成功完成。

    SessionId   Name   State      HasMoreData   Location   Command
    ---------   ----   -----      -----------   --------   -------
    1           Job1   Completed  True          Server01   Get-Eventlog system
    
  3. 若要获取作业的结果,请使用 Receive-Job cmdlet。 由于作业结果会自动返回到作业对象所在的计算机,因此可以使用本地 Receive-Job 命令获取结果。

    以下命令使用 Receive-Job cmdlet 获取作业的结果。 它使用会话 ID 来标识作业。 此命令将作业结果保存在 $results 变量中。 还可以将结果重定向到文件。

    $results = Receive-Job -id 1
    

启动将结果保留在远程计算机上的远程作业

若要在远程计算机上启动使命令结果保留在远程计算机上的作业,请使用 Invoke-Command cmdlet 在远程计算机上运行 Start-Job 命令。 可以使用此方法在多台计算机上运行作业。

远程运行 Start-Job 命令时,作业对象在远程计算机上创建,作业结果在远程计算机上维护。 从作业的角度来看,所有操作都是本地操作。 你只是远程运行命令来管理远程计算机上的本地作业。

  1. Invoke-Command使用 cmdlet 在远程计算机上运行Start-Job命令。

    此命令需要 PSSession (持久性连接) 。 如果使用 的 Invoke-Command ComputerName 参数建立临时连接,则返回作业对象时, Invoke-Command 命令被视为已完成。 因此,临时连接关闭,作业被取消。

    以下命令使用 New-PSSession cmdlet 创建连接到 Server01 计算机的 PSSession。 命令将 PSSession 保存在 变量中 $s

    $s = New-PSSession -computername Server01
    

    下一个命令使用 Invoke-Command cmdlet 在 PSSession 中运行 Start-Job 命令。 命令 Start-JobGet-Eventlog 命令括在大括号中。

    Invoke-Command -session $s -scriptblock {
      Start-Job -scriptblock {Get-Eventlog system}}
    

    结果类似于以下示例输出。

    Id       Name    State      HasMoreData     Location   Command
    --       ----    -----      -----------     --------   -------
    2        Job2    Running    True            Localhost  Get-Eventlog system
    

    远程运行 Start-Job 命令时, Invoke-Command 将返回返回的相同类型的作业对象 Start-Job 。 可以将作业对象保存在变量中,也可以使用 Get-Job 命令获取作业。

    请注意,即使作业在 Server01 计算机上运行, Location 属性的值也显示作业在本地计算机上运行,称为“LocalHost”。 由于作业对象是在 Server01 计算机上创建的,并且作业在同一台计算机上运行,因此它被视为本地后台作业。

  2. 若要管理远程作业,请使用 作业 cmdlet。 由于作业对象位于远程计算机上,因此需要运行远程命令来获取、停止、等待或检索作业结果。

    若要查看作业是否已完成,请使用 Invoke-Command 命令在连接到 Server01 计算机的 PSSession 中运行 Get-Job 命令。

    Invoke-Command -session $s -scriptblock {Get-Job}
    

    该命令返回一个作业对象。 作业对象的 State 属性显示命令已成功完成。

    SessionId   Name  State      HasMoreData   Location   Command
    ---------   ----  -----      -----------   --------   -------
    2           Job2  Completed  True          LocalHost   Get-Eventlog system
    
  3. 若要获取作业的结果,请使用 Invoke-Command cmdlet 在连接到 Server01 计算机的 PSSession 中运行 Receive-Job 命令。

    以下命令使用 Receive-Job cmdlet 获取作业的结果。 它使用会话 ID 来标识作业。 此命令将作业结果保存在 变量中 $results 。 它使用 的 Receive-Job Keep 参数将结果保留在远程计算机上的作业缓存中。

    $results = Invoke-Command -session $s -scriptblock {
      Receive-Job -SessionId 2 -Keep
    }
    

    还可以将结果重定向到本地或远程计算机上的文件。 以下命令使用重定向运算符将结果保存在 Server01 计算机上的文件中。

    Invoke-Command -session $s -command {
      Receive-Job -SessionId 2 > c:\logs\pslog.txt
    }
    

如何作为分离的进程运行

如前所述,终止父会话时,所有正在运行的子作业及其子进程都会终止。 可以在本地计算机上使用远程处理来运行未附加到当前 PowerShell 会话的作业。

在本地计算机上Create新的 PowerShell 会话。 用于 Invoke-Command 在此会话中启动作业。 Invoke-Command 允许断开远程会话并终止父会话。 稍后,可以启动新的 PowerShell 会话并连接到以前断开连接的会话,以继续监视作业。 但是,当原始 PowerShell 会话终止时,返回到原始 PowerShell 会话的任何数据都将丢失。 重新连接时,仅返回断开连接后生成的新数据对象。

# Create remote session on local machine
PS> $session = New-PSSession -cn localhost

# Start remote job
PS> $job = Invoke-Command -Session $session -ScriptBlock { 1..60 | % { sleep 1; "Output $_" } } -AsJob
PS> $job

Id     Name     PSJobTypeName   State         HasMoreData     Location      Command
--     ----     -------------   -----         -----------     --------      -------
1      Job1     RemoteJob       Running       True            localhost     1..60 | % { sleep 1; ...

# Disconnect the job session
PS> Disconnect-PSSession $session

Id Name         Transport ComputerName    ComputerType    State         ConfigurationName     Availability
-- ----         --------- ------------    ------------    -----         -----------------     ------------
1 Runspace1     WSMan     localhost       RemoteMachine   Disconnected  Microsoft.PowerShell          None

PS> $job

Id     Name     PSJobTypeName   State         HasMoreData     Location      Command
--     ----     -------------   -----         -----------     --------      -------
1      Job1     RemoteJob       Disconnected  True            localhost     1..60 | % { sleep 1;

# Reconnect the session to a new job object
PS> $jobNew = Receive-PSSession -Session $session -OutTarget Job
PS> $job | Wait-Job | Receive-Job
Output 9
Output 10
Output 11
...

对于此示例,作业仍附加到父 PowerShell 会话。 但是,父会话不是运行 的原始 Invoke-Command PowerShell 会话。

另请参阅