执行命令时如何忽略PowerShell中的特定错误?
How to ignore specific error in PowerShell when executing a command?
我知道 ErrorAction
论点,还有 $ErrorActionPreference
、$Error
和 $
.
上下文
我想解决的问题是当 运行 一个外部命令(例如 choco 或 git)它给出了应该警告或什至没有警告的错误,至少在我的任务上下文中.
由于它们的退出代码,PowerShell 认为该结果在任何意义上都是错误,例如将红色写入输出等,这在我的任务上下文中是不可取的。
我可以使用 -ErrorAction
或 2> $null
抑制这些命令错误输出,但我对通过这种方式完全消失 any 错误有一种不好的感觉特定命令。
我只想忽略已知的 "not a problem in this context for me" 类型错误。
问题
有没有什么方法可以忽略某些特定的命令错误,但正常处理所有其他错误情况?
我以前用 git 遇到过这种情况,然后使用 $LASTEXITCODE
.
解决了这个问题
不确定它是否适用于您的情况,或者是否适用于 choco,因为我没有遇到过问题。
# using git in powershell console sends everything to error stream
# this causes red text when it's not an error which is annoying
# 2>&1 redirects all to stdout, then use exit code to 'direct' output
$git_output = Invoke-Expression "& [git pull etc] 2>&1"
# handle output using exitcode
if ($LASTEXITCODE -ne 0) { throw $git_output }
else { Write-Output $git_output }
在常规控制台中 window,在 PowerShell v3 及更高版本中,stderr 行打印就像 stdout 行.
这是可取的,因为 stderr 不仅被许多程序用于报告真正的错误,而且还用于报告任何 非数据 ,例如状态消息.
Stderr 行(除非重定向 - 见下文)直接通过控制台打印(而 stdout 行被发送到 PowerShell 的成功输出流,在那里它们可以收集在一个变量中,通过管道发送,或使用 >
/ >>
).
重定向
遗憾的是,PowerShell ISE,即使在 v5.1,确实在red中以与PowerShell错误相同的格式打印标准错误行[=46] =]
使用 PowerShell 扩展的 - Visual Studio Code 没有这个问题,并且总体上值得迁移到,因为所有未来的开发工作都将集中在那里,并且它也适用于跨平台PowerShell Core 版本。
行为良好的控制台应用程序仅使用它们的退出代码来表示成功(退出代码 0
) 与失败(任何非零退出代码)。 PowerShell 将最近调用的控制台应用程序的退出代码保存在其 自动 $LASTEXITCODE
变量 .
中
顺便说一句:
- 公共参数
-ErrorAction
和-ErrorVariable
不能与外部程序一起使用。
- 同样,自 PowerShell v5.1 / PowerShell Core 6.2 起,首选项变量
$ErrorActionPreference
无效(除了 意外 ,由于 this bug。 0-预览.4).
try
/ catch
不能用于检测和处理外部程序的故障。
- 有关 PowerShell 复杂错误处理规则的全面概述,请参阅 this GitHub docs issue。
注意:我在下面的示例中使用了以下外部命令,它们产生 1 行 stdout 和 1 行 stderr 输出(注意重定向 >&2
由 cmd
处理,不是 PowerShell,因为它在 '...'
里面;它用于产生 stderr 输出):
cmd /c 'echo stdout & echo stderr >&2'
通过非零退出代码 (exit 1
) 使命令信号 失败 的变体:
cmd /c 'echo stdout & echo stderr >&2 & exit 1'
因此,通常以下内容就足够了:
$stdOut = cmd /c 'echo stdout & echo stderr >&2' # std*err* will print to console
if ($LASTEXITCODE -ne 0) { Throw "cmd failed." } # handle error
这会在变量 $stdout
中捕获 stdout 输出并将 stderr 输出传递到控制台。
如果你想收集以后的stderr输出并且只在[=92=的情况下显示它们]错误:
$stdErr = @() # initialize array for collecting stderr lines.
# Capture stdout output while collecting stderr output in $stdErr.
$stdOut = cmd /c 'echo stdout & echo stderr >&2 & exit 1' 2>&1 | Where-Object {
$fromStdErr = $_ -is [System.Management.Automation.ErrorRecord]
if ($fromStdErr) { $stdErr += $_.ToString() }
-not $fromStdErr # only output line if it came from stdout
}
# Throw an error, with the collected stderr lines included.
if ($LASTEXITCODE -ne 0) {
Throw "cmd failed with the following message(s): $stdErr"
}
注意 2>&1
重定向,它指示 PowerShell 通过管道(流 1
,错误流)发送 stderr 行(流 2
,错误流)成功流)。
在 Where-Object
块中,$_ -is [System.Management.Automation.ErrorRecord]
用于标识 stderr 行,因为 PowerShell 在该实例中包装了这些行类型。
或者,您可以在临时文件 (2>/path/to/tmpfile
) 中收集 stderr 输出,读取其内容,然后将其删除。
This GitHub issue 提议在 变量 中引入收集重定向 stderr 输出的选项,类似于您如何询问 cmdlets通过公共参数
-ErrorVariable
.
收集变量中的错误
有两个注意事项:
本质上,通过仅打印 stderr 行 later,与 stdout 输出相关的特定上下文可能会丢失.
由于 bug as of Windows PowerShell v5.1 / PowerShell Core 6.2.0,$ErrorActionPreference = Stop
不能 生效,因为 2>&1
重定向一旦收到第一个 stderr 行,就会触发 脚本终止错误。
如果您想有选择地对接收到的 stderr 行采取行动:
注:
本质上,当你处理这些行时,你还不知道程序最终会报告失败还是成功。
$ErrorActionPreference = 'Stop'
警告也适用于此。
以下示例过滤掉 stderr 行 stderr1
并将行 stderr2
以红色打印到控制台(仅文本,不像 PowerShell 错误)。
$stdOut = cmd /c 'echo stdout & echo stderr1 >&2 & echo stderr2 >&2' 2>&1 |
ForEach-Object {
if ($_ -is [System.Management.Automation.ErrorRecord]) { # stderr line
$stdErrLine = $_.ToString()
switch -regex ($stdErrLine) {
'stderr1' { break } # ignore, if line contains 'stderr1'
default { Write-Host -ForegroundColor Red $stdErrLine }
}
} else { # stdout line
$_ # pass through
}
}
# Handle error.
if ($LASTEXITCODE -ne 0) { Throw "cmd failed." }
我知道 ErrorAction
论点,还有 $ErrorActionPreference
、$Error
和 $
.
上下文
我想解决的问题是当 运行 一个外部命令(例如 choco 或 git)它给出了应该警告或什至没有警告的错误,至少在我的任务上下文中.
由于它们的退出代码,PowerShell 认为该结果在任何意义上都是错误,例如将红色写入输出等,这在我的任务上下文中是不可取的。
我可以使用 -ErrorAction
或 2> $null
抑制这些命令错误输出,但我对通过这种方式完全消失 any 错误有一种不好的感觉特定命令。
我只想忽略已知的 "not a problem in this context for me" 类型错误。
问题
有没有什么方法可以忽略某些特定的命令错误,但正常处理所有其他错误情况?
我以前用 git 遇到过这种情况,然后使用 $LASTEXITCODE
.
不确定它是否适用于您的情况,或者是否适用于 choco,因为我没有遇到过问题。
# using git in powershell console sends everything to error stream
# this causes red text when it's not an error which is annoying
# 2>&1 redirects all to stdout, then use exit code to 'direct' output
$git_output = Invoke-Expression "& [git pull etc] 2>&1"
# handle output using exitcode
if ($LASTEXITCODE -ne 0) { throw $git_output }
else { Write-Output $git_output }
在常规控制台中 window,在 PowerShell v3 及更高版本中,stderr 行打印就像 stdout 行.
这是可取的,因为 stderr 不仅被许多程序用于报告真正的错误,而且还用于报告任何 非数据 ,例如状态消息.
Stderr 行(除非重定向 - 见下文)直接通过控制台打印(而 stdout 行被发送到 PowerShell 的成功输出流,在那里它们可以收集在一个变量中,通过管道发送,或使用
>
/>>
). 重定向
遗憾的是,PowerShell ISE,即使在 v5.1,确实在red中以与PowerShell错误相同的格式打印标准错误行[=46] =]
-
使用 PowerShell 扩展的
- Visual Studio Code 没有这个问题,并且总体上值得迁移到,因为所有未来的开发工作都将集中在那里,并且它也适用于跨平台PowerShell Core 版本。
行为良好的控制台应用程序仅使用它们的退出代码来表示成功(退出代码
0
) 与失败(任何非零退出代码)。 PowerShell 将最近调用的控制台应用程序的退出代码保存在其 自动$LASTEXITCODE
变量 . 中
顺便说一句:
- 公共参数
-ErrorAction
和-ErrorVariable
不能与外部程序一起使用。 - 同样,自 PowerShell v5.1 / PowerShell Core 6.2 起,首选项变量
$ErrorActionPreference
无效(除了 意外 ,由于 this bug。 0-预览.4). try
/catch
不能用于检测和处理外部程序的故障。- 有关 PowerShell 复杂错误处理规则的全面概述,请参阅 this GitHub docs issue。
- 公共参数
注意:我在下面的示例中使用了以下外部命令,它们产生 1 行 stdout 和 1 行 stderr 输出(注意重定向 >&2
由 cmd
处理,不是 PowerShell,因为它在 '...'
里面;它用于产生 stderr 输出):
cmd /c 'echo stdout & echo stderr >&2'
通过非零退出代码 (exit 1
) 使命令信号 失败 的变体:
cmd /c 'echo stdout & echo stderr >&2 & exit 1'
因此,通常以下内容就足够了:
$stdOut = cmd /c 'echo stdout & echo stderr >&2' # std*err* will print to console
if ($LASTEXITCODE -ne 0) { Throw "cmd failed." } # handle error
这会在变量 $stdout
中捕获 stdout 输出并将 stderr 输出传递到控制台。
如果你想收集以后的stderr输出并且只在[=92=的情况下显示它们]错误:
$stdErr = @() # initialize array for collecting stderr lines.
# Capture stdout output while collecting stderr output in $stdErr.
$stdOut = cmd /c 'echo stdout & echo stderr >&2 & exit 1' 2>&1 | Where-Object {
$fromStdErr = $_ -is [System.Management.Automation.ErrorRecord]
if ($fromStdErr) { $stdErr += $_.ToString() }
-not $fromStdErr # only output line if it came from stdout
}
# Throw an error, with the collected stderr lines included.
if ($LASTEXITCODE -ne 0) {
Throw "cmd failed with the following message(s): $stdErr"
}
注意
2>&1
重定向,它指示 PowerShell 通过管道(流1
,错误流)发送 stderr 行(流2
,错误流)成功流)。在
Where-Object
块中,$_ -is [System.Management.Automation.ErrorRecord]
用于标识 stderr 行,因为 PowerShell 在该实例中包装了这些行类型。
或者,您可以在临时文件 (2>/path/to/tmpfile
) 中收集 stderr 输出,读取其内容,然后将其删除。
This GitHub issue 提议在 变量 中引入收集重定向 stderr 输出的选项,类似于您如何询问 cmdlets通过公共参数 -ErrorVariable
.
有两个注意事项:
本质上,通过仅打印 stderr 行 later,与 stdout 输出相关的特定上下文可能会丢失.
由于 bug as of Windows PowerShell v5.1 / PowerShell Core 6.2.0,
$ErrorActionPreference = Stop
不能 生效,因为2>&1
重定向一旦收到第一个 stderr 行,就会触发 脚本终止错误。
如果您想有选择地对接收到的 stderr 行采取行动:
注:
本质上,当你处理这些行时,你还不知道程序最终会报告失败还是成功。
$ErrorActionPreference = 'Stop'
警告也适用于此。
以下示例过滤掉 stderr 行 stderr1
并将行 stderr2
以红色打印到控制台(仅文本,不像 PowerShell 错误)。
$stdOut = cmd /c 'echo stdout & echo stderr1 >&2 & echo stderr2 >&2' 2>&1 |
ForEach-Object {
if ($_ -is [System.Management.Automation.ErrorRecord]) { # stderr line
$stdErrLine = $_.ToString()
switch -regex ($stdErrLine) {
'stderr1' { break } # ignore, if line contains 'stderr1'
default { Write-Host -ForegroundColor Red $stdErrLine }
}
} else { # stdout line
$_ # pass through
}
}
# Handle error.
if ($LASTEXITCODE -ne 0) { Throw "cmd failed." }