将 powershell 输出和错误重定向到控制台(实时)和变量

Redirect powershell output and errors to console (in real-time) and to a variable

我想在 PowerShell 中重定向命令的输出,遵循这些规则:

这是我的测试,假设:

$command = "echo:"

测试错误重定向,并且:

$command = "ping 127.0.0.1"

测试实时输出。

  1. 输出是实时写入的,错误根本不会被重定向

    Invoke-Expression $command 2>&1 | Tee-Object -Variable out_content
    
  2. 输出是实时写入的,错误只会重定向到控制台

    Invoke-Expression ($command 2>&1) | Tee-Object -Variable out_content
    Invoke-Expression $command | Tee-Object -Variable out_content 2>&1
    
  3. 输出不是实时写入的,错误被正确重定向到两者

    (Invoke-Expression $command) 2>&1 | Tee-Object -Variable out_content
    

是否可以让这些规则一起工作?

前面的一些一般建议

  • Invoke-Expression should generally be avoided,因为它可能存在安全风险并引入引号问题;通常有更好、更安全的解决方案可用;最好养成回避的习惯Invoke-Expression,除非别无他法

  • 从来没有理由使用Invoke-Expression来简单地执行带有参数的外部程序,例如ping 127.0.0.1;直接调用它 - 支持这种直接调用是任何 shell 的核心功能,PowerShell 也不例外。

  • I如果您确实需要将命令存储在变量中或将其作为参数 稍后调用,使用脚本块 ({ ... });例如,不使用 $command = 'ping 127.0.0.1',而是使用 $command = { ping 127.0.0.1 },并根据需要使用 &call operator, or ., the dot-sourcing operator.
    调用该脚本块 当调用外部程序时,两个运算符表现出相同的行为;当调用 PowerShell 本地命令 时,& 子范围 中执行代码,而 .(通常)执行在调用者的 current 范围内。


Invoke-Expression $command 2>&1 没有像预期的那样工作看起来像一个 bug(从 PowerShell Core 7.0.0 开始- preview.3) 并已在 this GitHub issue.

中报告

关于 解决方法 你的问题:

PetSerAl,和之前无数次一样,在问题的评论中提供了解决方案:

& { Invoke-Expression $command } 2>&1 | Tee-Object -Variable out_content

{ ... } 是包含 Invoke-Expression 调用的脚本块文字,它使用调用运算符 & 调用,它启用应用流重定向表达式 2>&1 & 调用,它绕过了这个错误。

如果 $command 包含您想在当前范围内直接执行的 PowerShell 本机命令,例如函数定义,您将使用 . 而不是&.