我想按照以下规则重定向 PowerShell 中命令的输出:
命令存储到变量中
输出必须实时写入控制台(即“ping”结果),包括错误
输出必须存储到变量中,包括错误(这里不强制要求实时)
这是我的测试,假设:
$command = "echo:"
测试错误重定向,并且:
$command = "ping 127.0.0.1"
测试实时输出。
输出是实时写入的,错误根本不会重定向
Invoke-Expression $command 2>&1 | Tee-Object -Variable out_content
输出是实时写入的,错误仅重定向到控制台
Invoke-Expression ($command 2>&1) | Tee-Object -Variable out_content
Invoke-Expression $command | Tee-Object -Variable out_content 2>&1
输出不是实时写入的,错误会正确重定向到两者
(Invoke-Expression $command) 2>&1 | Tee-Object -Variable out_content
是否有可能让这些规则一起发挥作用?
一些一般性建议放在前面:
Invoke-Expression
通常应避免,因为它可能会带来安全风险并引入令人头痛的引用;通常有更好、更安全的解决方案可用;最好养成避免Invoke-Expression
的习惯,除非没有其他解决办法。
永远没有理由使用
Invoke-Expression
来简单地执行带有参数的外部程序,例如ping 127.0.0.1
;只需直接调用它 - 支持此类直接调用是任何 shell 的核心功能,PowerShell 也不例外。
I如果您确实需要将命令存储在变量中或将其作为参数传递以供稍后调用,请使用脚本块 ({ ... }
);例如,使用
$command = 'ping 127.0.0.1'
代替
$command = { ping 127.0.0.1 }
,并根据需要使用
&
(调用运算符)或
.
(点采购运算符)调用该脚本块。 当调用
&
在子范围中执行代码,而
.
(通常)在调用者的当前范围中执行。
Invoke-Expression $command 2>&1
无法按预期工作,看起来像一个bug(从 PowerShell Core 7.0.0-preview.3 开始),并已在 GitHub 问题 #10476 中报告。 至于您的问题的
解决方法:
PetSerAl,正如之前无数次一样,在对该问题的评论中提供了解决方案:
& { Invoke-Expression $command } 2>&1 | Tee-Object -Variable out_content
{ ... }
是包含
Invoke-Expression
调用的脚本块文字,它是通过调用运算符
&
调用的,它可以将流重定向表达式
2>&1
应用于
&
调用,这绕过了错误。
如果 $command
包含您想要在当前范围内直接执行的 PowerShell 本机命令(例如函数定义),您可以使用
.
而不是
&
。
替代方案:
在要评估的字符串中包含2>&1
重定向:
Invoke-Expression "$command 2>&1" | Tee-Object -Variable out_content