问题描述
在不将输出保存到变量的情况下运行命令将导致任何流的输出可见,但唉,我需要将输出写入变量。
& terraform $action $arguments
最初我开始使用它。但是,只有成功流被写入变量(如预期)。
$res = & terraform $action $arguments
于是我咨询了docs for about_Redirection,但问题是,当我将错误流(或所有流)重定向到成功流时,我仍然只看到成功流写入变量。我做了几次尝试,都失败了。
$res = & terraform $action $arguments 2>&1
$res = & terraform $action $arguments *>&1
$res = & terraform $action $arguments *>&1 | ForEach-Object { $_.ToString() }
但是,如果我将错误流重定向到一个文件,那么该流将按预期写入。
$res = & terraform $action $arguments 2>> terraform-errors.log
如何将所有流的输出写入变量?
解决方法
我终于找到了答案,问题出在设置 $ErrorActionPreference = Stop
上。
当终止发生时,脚本在重定向输出之前被终止。要解决此问题,必须更改错误操作首选项,然后可以使用 Invoke-Expression
和一些 common parameters 将错误和输出发送到变量。
$ErrorActionPreference = "SilentlyContinue"
Invoke-Expression "& terraform $action $arguments 2>&1" -ErrorVariable terraformError -OutVariable terraformState | Out-Null
$ErrorActionPreference = "Stop"
### Check if there was an error.
if ($terraformError) {
throw $terraformError
}
为什么不使用 -ErrorAction
来更改错误操作首选项?
遗憾的是 -ErrorAction
仅适用于非终止错误。由于脚本的错误操作首选项是 Stop
,这意味着无论 Invoke-Expression
公共参数的值如何,-ErrorAction
命令都将始终触发终止错误。
要解决此问题,必须在运行 Invoke-Expression
命令之前更改错误操作首选项,然后在运行完成后更改回来。
为什么输出通过管道传送到 Out-Null
?
尽管将错误和输出保存到变量中,但输出也会流式传输到控制台,而无需通过管道将其传输到 Out-Null
。
显然这是可选的,因为在某些情况下可能可以接受/预期输出也将流式传输到控制台。