【问题标题】:Capture Write-Host output and exit code from Invoke-Command on a Remote System从远程系统上的 Invoke-Command 捕获 Write-Host 输出和退出代码
【发布时间】:2018-03-27 23:56:43
【问题描述】:

我有一个位于远程系统上的脚本。

在 C:\tmp\hgttg.ps1 下的服务器“web12”上:

 Write-Host "Don't Panic"
 exit 42

我使用 Invoke-Command 从我的本地机器(两个系统都运行 v4.0)调用此脚本:

$svr = "web12"
$cmd = "C:\tmp\hgttg.ps1"
$result = Invoke-Command -ComputerName $svr -ScriptBlock {& $using:cmd}

这会在执行时导致以下输出:

> $result = Invoke-Command -ComputerName $svr -ScriptBlock {& $using:cmd}
Don't Panic
> $result
>

($result 没有设置,直接输出到控制台,不好!)经过大量的网络搜索和故障排除,我得到了一些改进:

> $result = Invoke-Command -ComputerName $svr -ScriptBlock {& $using:cmd; $LASTEXITCODE}
Don't Panic
> $result
42
>

现在我可以捕获返回代码,但输出仍会直接发送到控制台。这是我所能得到的。在我已经尝试过的一长串事情中,以下都没有奏效:

  • 使用带有-OutVariable out 的“Invoke-Expression”代替“&”;新对象 -TypeName PSCustomObject -Property @{code=$LASTEXITCODE;输出=$out}

这会产生输出:

> $result
code           : 42
output         : 
PSComputerName : web12
RunspaceId     : aaa00a00-d1fa-4dd6-123b-aa00a00000000
> 
  • 尝试了上述两次迭代,在内部和外部命令的末尾使用 '4>&1' 和 '*>&1',没有变化。

  • 尝试了以下各项:

    1. "& $using:cmd | Tee-Object -Variable out; $out"
    2. "& $using:cmd >$out;$out"
    3. "$out = & $using:cmd;$out"

    (丢弃返回码只是为了得到输出)同样,没有变化。

  • 还尝试过:'& $using:cmd >> C:\tmp\output.log; $LASTEXITCODE'。生成的文件是空的,文本还是输出到本地终端。

我确信我缺少一些明显的东西,但到目前为止,我所遇到的只是死胡同。有什么建议吗?

【问题讨论】:

  • "我确定我缺少一些明显的东西" - 不要使用 write-host。 write-host 的全部意义在于它不是函数返回值,而是写入主机屏幕的文本。改用 Write-Output(或不使用)。
  • @TessellatingHeckler 我使用的示例是故意的,我实际调用的脚本会将大量信息显示在屏幕上,然后返回一个退出代码。我无法更改目标脚本,但我仍然需要查看它们写出的内容。
  • 如果它们是使用标准输出的本机命令 (.exes),那么它们不会写入屏幕,并且它们的输出应该是可捕获的。如果它们是使用 Write-Host 的 PowerShell 脚本,则它们已损坏并需要修复。如果您无法触摸脚本,您唯一的其他选择是将您的环境升级到 PowerShell 5.1,它可以远程输出 write-host。如果是.exes直接写到控制台,不知道有没有什么办法。

标签: powershell powershell-4.0 powershell-remoting exit-code write-host


【解决方案1】:

PSv4-(4.x 或更低版本)上,您只是无法捕获Write-Host 输出 - 它总是直接转到控制台。

PSv5+ 中,Write-Host(也)写入新引入的 信息流,新引入的 Write-Information cmdlet 旨在写入; 它的号码是6

因此,如果您的目标主机运行 PSv5+,您可以使用以下内容;请注意*> 如何通过将 (&) 重定向到成功流 (1) 来捕获所有 输出流,但您可以使用 6> 选择性地捕获信息流):

$result = Invoke-Command -ComputerName $svr -ScriptBlock {& $using:cmd *>&1; $LASTEXITCODE}
$output = $result[0..($result.Count-2)]
$exitCode = $result[-1]

【讨论】:

    猜你喜欢
    • 2018-12-02
    • 1970-01-01
    • 2016-12-12
    • 1970-01-01
    • 2011-10-24
    • 1970-01-01
    • 1970-01-01
    • 2015-05-19
    • 2014-06-19
    相关资源
    最近更新 更多