从远程系统上的 Invoke-Command 捕获 Write-Host 输出和退出代码
Capture Write-Host output and exit code from Invoke-Command on a Remote System
我在远程系统上有一个脚本。
在服务器 "web12" 下 C:\tmp\hgttg.ps1:
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
>
现在我可以捕获 return 代码,但输出仍然直接进入控制台。这是我能得到的。在我已经尝试过的一长串事情中,以下 none 行得通:
- 而不是 '&' 使用 'Invoke-Expression' with -OutVariable out;新对象 -TypeName PSCustomObject -属性 @{code=$LASTEXITCODE;输出=$out}
这会产生输出:
> $result
code : 42
output :
PSComputerName : web12
RunspaceId : aaa00a00-d1fa-4dd6-123b-aa00a00000000
>
尝试在内部和外部命令末尾使用“4>&1”和“*>&1”进行上述两次迭代,没有变化。
尝试了以下各项:
- "& $using:cmd | Tee-Object -变量输出;$out"
- "& $using:cmd >$out; $out"
- "$out = & $using:cmd;$out"
(丢弃 return 代码只是为了获得输出)同样,没有变化。
也尝试过:'& $using:cmd >> C:\tmp\output.log; $LASTEXITCODE'。生成的文件是空的,文本仍然输出到本地终端。
我确定我遗漏了一些明显的东西,但到目前为止我遇到的都是死胡同。有什么建议吗?
在 PSv4-(版本 4.x 或以下)上,你 无法 捕获 Write-Host
输出 - 它总是直接进入控制台。
在PSv5+中,Write-Host
(也)写入新引入的信息流,新引入的[=13] =] cmdlet 旨在写入; 它的编号是6
.
因此,如果您的目标主机运行 PSv5+,您可以使用以下命令;请注意 *>
如何通过将它们重定向 (&
) 到成功流 (1
) 来捕获 all 输出流,但是您可以使用 6>
有选择地捕获信息流):
$result = Invoke-Command -ComputerName $svr -ScriptBlock {& $using:cmd *>&1; $LASTEXITCODE}
$output = $result[0..($result.Count-2)]
$exitCode = $result[-1]
我在远程系统上有一个脚本。
在服务器 "web12" 下 C:\tmp\hgttg.ps1:
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
>
现在我可以捕获 return 代码,但输出仍然直接进入控制台。这是我能得到的。在我已经尝试过的一长串事情中,以下 none 行得通:
- 而不是 '&' 使用 'Invoke-Expression' with -OutVariable out;新对象 -TypeName PSCustomObject -属性 @{code=$LASTEXITCODE;输出=$out}
这会产生输出:
> $result
code : 42
output :
PSComputerName : web12
RunspaceId : aaa00a00-d1fa-4dd6-123b-aa00a00000000
>
尝试在内部和外部命令末尾使用“4>&1”和“*>&1”进行上述两次迭代,没有变化。
尝试了以下各项:
- "& $using:cmd | Tee-Object -变量输出;$out"
- "& $using:cmd >$out; $out"
- "$out = & $using:cmd;$out"
(丢弃 return 代码只是为了获得输出)同样,没有变化。
也尝试过:'& $using:cmd >> C:\tmp\output.log; $LASTEXITCODE'。生成的文件是空的,文本仍然输出到本地终端。
我确定我遗漏了一些明显的东西,但到目前为止我遇到的都是死胡同。有什么建议吗?
在 PSv4-(版本 4.x 或以下)上,你 无法 捕获 Write-Host
输出 - 它总是直接进入控制台。
在PSv5+中,Write-Host
(也)写入新引入的信息流,新引入的[=13] =] cmdlet 旨在写入; 它的编号是6
.
因此,如果您的目标主机运行 PSv5+,您可以使用以下命令;请注意 *>
如何通过将它们重定向 (&
) 到成功流 (1
) 来捕获 all 输出流,但是您可以使用 6>
有选择地捕获信息流):
$result = Invoke-Command -ComputerName $svr -ScriptBlock {& $using:cmd *>&1; $LASTEXITCODE}
$output = $result[0..($result.Count-2)]
$exitCode = $result[-1]