Powershell 将 stderr 和 stdout 重定向到两个不同的地方

问题描述 投票:0回答:3

如何重定向

  • stderr 到日志文件
  • 标准输出到对象

我看过的东西:

>>
2>>
仅重定向到文件 .
-RedirectStandardOutput
-RedirectStandardError
仅再次重定向到文件。
| Out-File
无法重定向 stderr。
| Tee-Object
同样的问题。

powershell stdout stderr
3个回答
20
投票

连接

stdout
stderr
输出流的工作原理就像 PetSerAl 评论的那样,尽管语法不是最直观的。

2>&1
奇怪的语法意味着
stderr
(流2)将被添加到
stdout
(流1)中。由于这实际上不是您想要的,请尝试将 MS 页面中的另一个示例改编为 Powershell:

或者,您可以将输出重定向到一个位置,并将错误重定向到另一个位置。

dir file.xxx > 输出.msg 2> 输出.err

因此,

$ret = myCommand 2> errors.log

应在日志文件中发送错误,并在

$ret
变量中发送非错误。


7
投票

about_Redirection MSDN 文章中有全面的解释。

最小、完整且可验证的示例

stdout
到管道):

PS D:\PShell> -1,5,0,2| ForEach-Object { 15/$_ } 2>"$env:temp\err.txt" | Write-Output
-15
3
7.5

PS D:\PShell> Get-Content "$env:temp\err.txt"
Attempted to divide by zero.
At line:1 char:28
+ -1,5,0,2| ForEach-Object { 15/$_ } 2>"$env:temp\err.txt" | Write-Outpu ...
+                            ~~~~~
    + CategoryInfo          : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException


PS D:\PShell> 

另一个例子(

stdout
反对):

PS D:\PShell> $x = -1,5,0,2| ForEach-Object { 15/$_} 2>"$env:temp\err.txt"

PS D:\PShell> $x
-15
3
7.5

-1
投票
function GetAnsVal {
    param([Parameter(Mandatory=$true, ValueFromPipeline=$true)][System.Object[]][AllowEmptyString()]$Output,
          [Parameter(Mandatory=$false, ValueFromPipeline=$true)][System.String]$firstEncNew,
          [Parameter(Mandatory=$false, ValueFromPipeline=$true)][System.String]$secondEncNew
    )
    function ConvertTo-Encoding ([string]$From, [string]$To){#"UTF-8" "CP866" "ASCII" "windows-1251"
        Begin{
            $encFrom = [System.Text.Encoding]::GetEncoding($from)
            $encTo = [System.Text.Encoding]::GetEncoding($to)
        }
        Process{
            $Text=($_).ToString()
            $bytes = $encTo.GetBytes($Text)
            $bytes = [System.Text.Encoding]::Convert($encFrom, $encTo, $bytes)
            $encTo.GetString($bytes)
        }
    }
    $all = New-Object System.Collections.Generic.List[System.Object];
    $exception = New-Object System.Collections.Generic.List[System.Object];
    $stderr = New-Object System.Collections.Generic.List[System.Object];
    $stdout = New-Object System.Collections.Generic.List[System.Object]
    $i = 0;$Output | % {
        if ($_ -ne $null){
            if ($_.GetType().FullName -ne 'System.Management.Automation.ErrorRecord'){
                if ($_.Exception.message -ne $null){$Temp=$_.Exception.message <#| ConvertTo-Encoding $firstEncNew $secondEncNew#>;$all.Add($Temp);$exception.Add($Temp)}
                elseif ($_ -ne $null){$Temp=$_ <#| ConvertTo-Encoding $firstEncNew $secondEncNew#>;$all.Add($Temp);$stdout.Add($Temp)}
            } else {
                #if (MyNonTerminatingError.Exception is AccessDeniedException)
                $Temp=$_.Exception.message <#| ConvertTo-Encoding $firstEncNew $secondEncNew#>;
                $all.Add($Temp);$stderr.Add($Temp)
            }   
         }
    $i++
    }
    [hashtable]$return = @{}
    $return.Meta0=$all;$return.Meta1=$exception;$return.Meta2=$stderr;$return.Meta3=$stdout;
    return $return
}
Add-Type -AssemblyName System.Windows.Forms;
& C:\Windows\System32\curl.exe 'api.ipify.org/?format=plain' 2>&1 | set-variable Output;
$r = & GetAnsVal $Output
[Console]::Write("exception:`n");
$r.Meta1
[Console]::Write("stderr:`n");
$r.Meta2
[Console]::Write("stdout:`n");
$r.Meta3
© www.soinside.com 2019 - 2024. All rights reserved.