【问题标题】:Can't repeatedly receive output from job无法重复接收作业的输出
【发布时间】:2015-08-10 11:26:53
【问题描述】:

我可以在 ScheduledJob 中使用 Start-Job 吗?

故事如下:我正在使用来自System.Management.Automation、Remoting 和 Runspaces 的 .Net 类从我的应用程序内部使用 PowerShell Remoting。 我运行一个脚本,在远程主机上创建一个 ScheduledJob,它使用 Hyper-V 做一些基本的事情,比如说Restart-Vm。操作本身按预期执行,就像我在此远程主机上的控制台中运行它一样。

虽然有一个区别——如果我把它放到控制台上,我会立即得到操作的结果。例如,如果 VM 已禁用,我将收到“当虚拟机处于当前状态时无法执行操作”。对于 SJ,当某些 SJ 触发器被激活并且 SJ 运行时,我不可能在收到我的 Restart-Vm 命令后立即获得它的结果。相反,我必须检查 SJ 被触发时创建的相应 BackgroundJob 并检查其状态并接收其结果。这不行,因为我的应用程序必须将此类事件写入远程机器上的 EventLog。即使Restart-Vm 操作不成功,也不会引发异常,而且我显然无法写入计划作业正文中的 EventLog。

我认为解决方案可能是这样的:在计划的作业中创建一个新作业,使该作业执行目标操作并将处理程序绑定到该作业的状态更改事件,该事件将写入 EventLog。

但是,当我实现这个时

Start-Job -ScriptBlock { params($guid) Get-Vm $guid | Restart-Vm -Force; } -ArgumentList $id;

它失败了。它是这样发生的:SJ 被解雇,相应的 Job 被创建,我检查它的状态 - 它是 Completed 并且它是HasMoreData。当我执行Receive-Job 时,出现此错误

Receive-Job : Parameter set cannot be resolved using the specified named parameters.
At line:1 char:8
+ $res | receive-job
+        ~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (System.Manageme...n.PSRemotingJob:PSObject) [Receive-Job], ParameterBindingEx 
   ception
    + FullyQualifiedErrorId : AmbiguousParameterSet,Microsoft.PowerShell.Commands.ReceiveJobCommand

我尝试使用-AsJob 开关运行Restart-Vm 操作,传递凭据,但没有任何效果。

2015 年 6 月 5 日更新

其实这个问题是因为我需要捕获Restart-Vm抛出的异常。直到最近我才意识到我必须在调用Restart-Vm 时指定-ErrorAction Stop-ErrorVariable 参数,这样我才能控制它的执行。所以不再需要像嵌套作业这样的技巧了。

【问题讨论】:

  • 如何获得$res
  • $res 是从我的预定作业发起的作业中收到的数据,也是作业。它的状态是“正在运行”。我这样检索它: $res = Get-Job |接收工作。我确保 Get-Job 只返回一份工作 - 刚刚开始的工作。
  • 我认为你不能Receive-Job 两次
  • 嗯,我为什么不能呢?这是 2 个不同的工作,具有不同的 ID、名称和状态,一个是另一个看起来不错的结果。有什么合理的解释为什么不可能吗?我的意思是我已经用谷歌搜索了很多,但仍然没有找到关于这个案例的任何详细信息。

标签: powershell jobs


【解决方案1】:

执行语句$res = Get-Job | Receive-Job$res 的值是从作业接收到的输出。该输出不是可以再次输入Receive-Job作业

演示:

PS C:\> Start-Job -ScriptBlock { 'foo' }

Id  Name  PSJobTypeName  State    HasMoreData  Location   Command
--  ----  -------------  -----    -----------  --------   -------
6   Job6  BackgroundJob  Running  True         localhost  'foo'

PS C:\> $res = Get-Job | Receive-Job
PS C:\> $res
foo
PS C:\> $res | Receive-Job
Receive-Job : The input object cannot be bound to any parameters for the command
either because the command does not take pipeline input or the input and its
properties do not match any of the parameters that take pipeline input.
At line:1 char:8
+ $res | Receive-Job
+        ~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (foo:PSObject) [Receive-Job], ...
    + FullyQualifiedErrorId : InputObjectNotBound,Microsoft.PowerShell.Comman...

如果要多次接收,则需要保留作业对象(或其 ID):

PS C:\> $job = Start-Job -ScriptBlock { 'foo' }
PS C:\> $job | Receive-Job
foo
PS C:\> $job | Receive-Job
PS C:\> Get-Job -Id $job.Id | Receive-Job
PS C:\> _

【讨论】:

  • 好的,谢谢,所以似乎不得不放弃这种深奥的完成工作的想法。
  • @VarvaraKalinina 如果您想等待工作完成,请使用Wait-Job
  • 是的,我会按照你说的做,如果仍然需要它,请参阅我的帖子更新。不再需要嵌套作业。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
相关资源
最近更新 更多