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

Kan*_*pra 7 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"
Run Code Online (Sandbox Code Playgroud)

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

注意:如果我没有弄错,1是输出流,2是错误流,3是警告流.

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

Powershell -File "C:\myscript.ps1" 3>&2> "C:\log.txt"
Run Code Online (Sandbox Code Playgroud)

但是,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" 
Run Code Online (Sandbox Code Playgroud)

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

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

Ans*_*ers 6

通过运行PowerShell脚本时,详细,警告和调试流将合并到STDOUT中

powershell -File "C:\myscript.ps1"
Run Code Online (Sandbox Code Playgroud)

所以你不能再单独重定向它们了.只有错误流是不同的,因为它似乎要到标准输出和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>&2,1>&5...),PowerShell重定向仅支持重定向到文件(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"
Run Code Online (Sandbox Code Playgroud)

或者像这样:

powershell -Command ".\test.ps1 >out.txt 3>&1 2>&1"
Run Code Online (Sandbox Code Playgroud)

或(重定向所有流),如下所示:

powershell -Command ".\test.ps1 *>out.txt"
Run Code Online (Sandbox Code Playgroud)

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

powershell -Command ".\test.ps1 3>warning.log 2>error.log"
Run Code Online (Sandbox Code Playgroud)


Lie*_*ers 1

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

  3>&2>&1
Run Code Online (Sandbox Code Playgroud)

你应该这样做

  3>&1 2>&1
Run Code Online (Sandbox Code Playgroud)

改编自理解流

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
Run Code Online (Sandbox Code Playgroud)

应用于你的例子,这将变成

Powershell -File "C:\myscript.ps1" 3>&1 2>&1> "C:\log.txt"
Run Code Online (Sandbox Code Playgroud)

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

Powershell -File "C:\myscript.ps1" *> "C:\log.txt"
Run Code Online (Sandbox Code Playgroud)