gpt4 book ai didi

powershell - 执行命令时如何忽略PowerShell中的特定错误?

转载 作者:行者123 更新时间:2023-12-01 00:14:17 26 4
gpt4 key购买 nike

我知道 ErrorAction参数,还有 $ErrorActionPreference , $Error$ .

语境

我想解决的问题是,当运行外部命令(例如 choco 或 git)时,它会给出错误,至少在我的任务上下文中应该是警告或什至不警告。

由于它们的退出代码,PowerShell 认为该结果在任何意义上都是错误,例如将红色写入输出等,这在我的任务上下文中是不可取的。

我可以用 -ErrorAction 抑制这些命令错误输出或 2> $null ,但我对完全消失有一种不好的感觉任何 错误这种方式的特定命令。

我只想忽略已知的“在这种情况下对我来说不是问题”类型错误。

问题

有没有办法处理命令的错误,忽略一些特定的,但正常对待所有其他错误条件?

最佳答案

  • 在常规控制台窗口中 ,在 PowerShell v3 及更高版本中, stderr 行打印就像 stdout 行 .
  • 这是可取的,因为 许多程序使用 stderr 不仅报告真正的错误,还报告任何非数据的内容,例如状态消息 .
  • Stderr 行(除非重定向 - 见下文)直接通过控制台打印(而 stdout 行被发送到 PowerShell 的成功输出流,在那里它们可以收集在一个变量中,通过管道发送,或使用 >/>> 重定向)。
  • 遗憾的是, PowerShell ISE,即使在 v5.1 , 确实以红色打印 stderr 行 ,在 与 PowerShell 错误格式相同 .
  • Visual Studio Code PowerShell 扩展没有这个问题,一般来说值得迁移,因为所有 future 的开发工作都将集中在那里,并且它也适用于跨平台的 PowerShell Core 版本。
  • 表现良好的控制台应用程序仅使用其退出代码来表示成功(退出代码 0)与失败(任何非零退出代码) . PowerShell 将最近调用的控制台应用程序的退出代码保存在其 中。自动 $LASTEXITCODE变量 .
  • 作为旁白:
  • 常用参数-ErrorAction-ErrorVariable不能与外部程序一起使用。
  • 同样,偏好变量 $ErrorActionPreference没有影响(除了意外,由于 this bug ,从 PowerShell v5.1/PowerShell Core 6.2.0-preview.4 开始)。
  • try/catch不能用于检测和处理外部程序的故障。
  • 有关 PowerShell 复杂错误处理规则的全面概述,请参阅 this GitHub docs issue .

  • 注意:我在下面的示例中使用了以下外部命令,它们产生 1 行 stdout 和 1 行 stderr 输出(注意重定向 >&2cmd 处理,而不是 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 输出 仅在出现错误时才显示 :
    $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 也通过管道(流 2,成功流)发送 stderr 行(流 1,错误流)。
  • Where-Object块,$_ -is [System.Management.Automation.ErrorRecord]用于标识 stderr 行,因为 PowerShell 将此类行包装在该类型的实例中。

  • 或者,您可以在临时文件 ( 2>/path/to/tmpfile ) 中收集 stderr 输出,读取其内容,然后将其删除。

    This GitHub issue建议引入在变量中收集重定向 stderr 输出的选项,类似于您可以如何要求 cmdlet 通过公共(public)参数 -ErrorVariable 收集变量中的错误。 .

    有两个 警告 :
  • 本质上,通过稍后仅打印 stderr 行,可能会丢失与 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." }

    关于powershell - 执行命令时如何忽略PowerShell中的特定错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54549573/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com