Powershell将stderr和stdout重定向到两个不同的位置

wfauudbj  于 2023-02-08  发布在  Shell
关注(0)|答案(3)|浏览(160)

如何重定向

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

我看过的东西:
>>2>>仅重定向到文件。
-RedirectStandardOutput-RedirectStandardError仅再次重定向到文件。
| Out-File无法重定向标准错误。
| Tee-Object相同的问题。

nhaq1z21

nhaq1z211#

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
ftf50wuq

ftf50wuq2#

连接stdoutstderr输出流的工作原理与PetSerAl的评论类似,尽管语法不是最直观的。
2>&1的奇怪语法意味着stderr(流2)将被添加到stdout(流1)中,因为这不是您实际想要的,请尝试将MS页面中的另一个示例修改为Powershell:
或者,您可以将输出重定向到一个位置,而将错误重定向到另一个位置。
目录www.example.com〉输出消息2〉输出错误file.xxx > output.msg 2> output.err
因此,

$ret = myCommand 2> errors.log

应在日志文件中发送错误,在$ret变量中发送非错误。

avwztpqn

avwztpqn3#

about_Redirection MSDN文章中的全面说明。
A Minimal, Complete, and Verifiable example(*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

相关问题