将 powershell 输出和错误重定向到控制台(实时)和变量
Redirect powershell output and errors to console (in real-time) and to a variable
我想在 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
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 本机命令,例如函数定义,您将使用 .
而不是&
.
我想在 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
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 本机命令,例如函数定义,您将使用 .
而不是&
.