about_Remote_Jobs

简短说明

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

详细说明

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

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

    C:\PS> Enter-PSSession -computername Server01
    

    命令提示符会发生更改,显示现已连接 Server01 计算机。

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

    此命令将作业对象保存在 $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 文件的内容,可启动另一个交互式会话或运行远程命令。 如果要使用几个命令来调查和管理 PsLog.txt 文件中的数据,最好在 PSSession(持久连接)中运行这些命令。 有关 PSSession 的详细信息,请参阅 about_PSSession

    以下命令使用 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(如 Invoke-Command cmdlet)的 AsJob 参数。

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

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

  1. 以下命令使用 Invoke-Command 的 AsJob 参数在 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. 若要使用 Invoke-Command cmdlet 的 AsJob 参数管理作业,请使用 Job 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 命令获取作业。

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

  2. 若要管理远程作业,请使用 Job 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 会话的作业。

在本地计算机上创建新的 PowerShell 会话。 使用 Invoke-Command 在此会话中启动作业。 Invoke-Command 可断开远程会话的连接并终止父会话。 之后可启动新的 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 会话。

另请参阅