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

时间:2015-06-18 04:15:46

标签: powershell stream io-redirection

在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-Error Write-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,因为文件被警告流锁定。

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

3 个答案:

答案 0 :(得分:6)

通过

运行PowerShell脚本时,详细,警告和调试流将合并到STDOUT中
powershell -File "C:\myscript.ps1"

因此您无法再单独重定向它们。只有错误流是不同的,因为它似乎同时转到STDOUT和STDERR,它可以被1>以及2>重定向。

演示:

C:\>type test.ps1
$DebugPreference = "Continue"
$VerbosePreference = "Continue"
Write-Output "Output message"
Write-Error "Error message"
Write-Verbose "Verbose message"
Write-Warning "Warning message"
Write-Debug "Debug message"

C:\>powershell -File .\test.ps1
Output message
C:\test.ps1 : Error message
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,test.ps1

VERBOSE: Verbose message
WARNING: Warning message
DEBUG: Debug message

C:\>powershell -File .\test.ps1 2>nul 3>nul 4>nul 5>nul
Output message
VERBOSE: Verbose message
WARNING: Warning message
DEBUG: Debug message

C:\>powershell -File .\test.ps1 1>nul

C:\>_

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

C:\>powershell -Command ".\test.ps1 2>$null 3>$null 5>$null"
Output message
VERBOSE: Verbose message

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

C:\>powershell -Command ".\test.ps1 2>out.txt 3>&2"
At line:1 char:22
+ .\test.ps1 2>out.txt 3>&2
+                      ~~~~
The '3>&2' operator is reserved for future use.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : RedirectionNotSupported

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

C:\>powershell -Command ".\test.ps1 2>out.txt 3>>out.txt"
out-file : The process cannot access the file 'C:\out.txt' because it is being
used by another process.
At line:1 char: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"

答案 1 :(得分: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 :(得分:0)

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

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

本文来自Simon Wahlin