将输出流以外的两个或多个 Powershell 流重定向到同一个文件

Posted

技术标签:

【中文标题】将输出流以外的两个或多个 Powershell 流重定向到同一个文件【英文标题】:Redirect two or more Powershell streams other than output stream to the same file 【发布时间】:2015-09-03 13:24:46 【问题描述】:

在 Powershell 中,我们可以将标准输出流与任何其他流结合起来,然后将结果重定向(写入)到同一个文件。

例子:

Powershell -File "C:\myscript.ps1" 2>&1> "C:\log.txt"  
Powershell -File "C:\myscript.ps1" 3>&2>&1> "C:\log.txt"

假设我在 myscript.ps1 中使用 Write-ErrorWrite-Warning 语句,并且我只想将错误和警告写入同一个文件。

注意:如果我没记错的话,1是输出流,2是错误流,3是警告流。

我的第一个合乎逻辑的尝试是使用 3>&2> - 如果结合 1 和 2 有效,为什么不 3 和 2 ?见下文:

Powershell -File "C:\myscript.ps1" 3>&2> "C:\log.txt"

但是,3>&2> 不能作为有效的重定向运算符。

我可以尝试一下:

Powershell -File "C:\myscript.ps1" 3>"C:\warninglog.txt" 2>"C:\errorlog.txt" 但我真的很想写入同一个文件。

如果我尝试运行:

Powershell -File "C:\myscript.ps1" 3>"C:\log.txt" 2>"C:\log.txt" 

似乎错误流 (2) 永远不会被写入 log.txt,因为文件已被警告流锁定。

有没有办法将两个(或多个)输出流组合成一个流并将结果重定向到同一个文件?

【问题讨论】:

【参考方案1】:

您可以将错误和警告流分别重定向到输出流,而不是这样做

  3>&2>&1

你应该这样做

  3>&1 2>&1

改编自Understanding streams

function Write-Messages

    Write-Host "Host message"
    Write-Output "Output message"
    Write-Verbose "Verbose message"
    Write-Warning "Warning message"
    Write-Error "Error message"
    Write-Debug "Debug message"


$DebugPreference = "Continue"
$VerbosePreference = "Continue"

Write-Messages 3>&1 2>&1 > $env:TEMP\test.txt

应用于您的示例,这将成为

Powershell -File "C:\myscript.ps1" 3>&1 2>&1> "C:\log.txt"

或者您可以将所有流重定向到您的文件

Powershell -File "C:\myscript.ps1" *> "C:\log.txt"

【讨论】:

【参考方案2】:

当您通过以下方式运行 PowerShell 脚本时,详细、警告和调试流将合并到 STDOUT 中

powershell -File "C:\myscript.ps1"

因此您不能再单独重定向它们。只有错误流不同,因为它似乎同时进入 STDOUT 和 STDERR,可以通过 1>2> 重定向。

演示:

C:\>输入 test.ps1 $DebugPreference = "继续" $VerbosePreference = "继续" 写输出“输出消息” 写错误“错误信息” Write-Verbose “详细消息” 写警告“警告信息” 写调试“调试消息” C:\>powershell -File .\test.ps1 输出消息 C:\test.ps1:错误信息 + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException +fullyQualifiedErrorId:Microsoft.PowerShell.Commands.WriteErrorException,test.ps1 VERBOSE:详细信息 警告:警告信息 DEBUG:调试信息 C:\>powershell -File .\test.ps1 2>nul 3>nul 4>nul 5>nul 输出消息 VERBOSE:详细信息 警告:警告信息 DEBUG:调试信息 C:\>powershell -File .\test.ps1 1>nul C:\>_

如果您想单独重定向详细、警告或调试流,您必须使用 -Command 而不是 -File 并在 PowerShell 中执行重定向:

C:\>powershell -Command ".\test.ps1 2>$null 3>$null 5>$null" 输出消息 VERBOSE:详细信息

但是,在 CMD 中,您可以将任何句柄重定向到任何其他句柄(3>&21>&5、...),PowerShell redirection 仅支持重定向到文件 (3>C:\out.txt) 或成功输出流 (3>&1)。尝试重定向到任何其他流将引发错误:

C:\>powershell -Command ".\test.ps1 2>out.txt 3>&2" 在行:1 字符:22 + .\test.ps1 2>out.txt 3>&2 + ~~~~ '3>&2' 运算符保留供将来使用。 + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException + FullyQualifiedErrorId : 重定向不支持

将不同的流重定向到同一个文件:

C:\>powershell -Command ".\test.ps1 2>out.txt 3>>out.txt" out-file : 进程无法访问文件 'C:\out.txt' 因为它正在 被另一个进程使用。 在行:1 字符:1 + .\test.ps1 2>out.txt 3>>out.txt + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : OpenError: (:) [Out-File], IOException + FullyQualifiedErrorId : FileOpenFailure,Microsoft.PowerShell.Commands.OutFileCommand

如果您可以选择合并警告和成功输出,您可以执行以下操作:

powershell -Command ".\test.ps1 >out.txt 3>&1 2>error.log"

或者像这样:

powershell -Command ".\test.ps1 >out.txt 3>&1 2>&1"

或(重定向所有流)像这样:

powershell -Command ".\test.ps1 *>out.txt"

否则我看到的唯一选择是重定向到不同的文件:

powershell -Command ".\test.ps1 3>warning.log 2>error.log"

【讨论】:

【参考方案3】:

如果您想说将输出流捕获到一个变量中并将其他流捕获到另一个变量中,那么您可以使用子表达式来做到这一点:

$errorOutput = $( $output = & $command $arguments ) 2>&1

这是来自Simon Wahlin的一篇优秀文章

【讨论】:

以上是关于将输出流以外的两个或多个 Powershell 流重定向到同一个文件的主要内容,如果未能解决你的问题,请参考以下文章

如何组合输出流,以便输出一次到达多个位置?

哪个流在powershell中记录输出文件?

如何连接两个或多个 gzip 文件/流

kafka 基础介绍

如何使用向量合并另一个或文件中的两个或多个流?

JAVA 的输入与输出流当中,什么时候该使用字符流?什么时候该使用字节流?