【问题标题】:Powershell redirect stderr and stdout to two different placesPowershell 将 stderr 和 stdout 重定向到两个不同的地方
【发布时间】:2017-12-17 16:49:09
【问题描述】:

如何重定向

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

我看过的东西:

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

【问题讨论】:

  • . {$object = command} 2>&1 | Out-File logfile
  • @PetSerAl - 你能解释一下吗? 2>1 会将输出 stdout 和 stderr 都重定向到日志文件,不是吗?
  • 是的。但是赋值操作 ($object =) 已经捕获了常规输出,所以它已经从输出流中删除了。
  • @PetSerAl - 搞定了。非常简洁的解决方案。谢谢。

标签: powershell redirect stdout stderr


【解决方案1】:

加入stdoutstderr 输出流的工作方式与 PetSerAl 评论的一样,尽管语法不是最直观的。

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

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

dir file.xxx > output.msg 2> output.err

因此,

$ret = myCommand 2> errors.log

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

【讨论】:

  • 感谢 vonPryz。我在 powershell 中发现的一个大问题不是找到关于做什么的文档,而是找到“为什么”和“如何”工作的文档。知道 2>&1 将标准错误输入标准输出是关键。
【解决方案2】:

about_RedirectionMSDN 文章中的综合解释。

A Minimal, Complete, and Verifiable examplestdout 到管道):

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

【讨论】:

    【解决方案3】:
    cls
    function GetAnsVal {
        param([Parameter(Mandatory=$true, ValueFromPipeline=$true)][System.Object[]][AllowEmptyString()]$Output,
              [Parameter(Mandatory=$false, ValueFromPipeline=$true)][System.String]$firstEncNew="UTF-8",
              [Parameter(Mandatory=$false, ValueFromPipeline=$true)][System.String]$secondEncNew="CP866"
        )
        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
    $Meta2=""
    foreach ($el in $r.Meta2){
        $Meta2+=$el
    }
    $Meta2=($Meta2 -split "[`r`n]") -join "`n"
    $Meta2=($Meta2 -split "[`n]{2,}") -join "`n"
    [Console]::Write("stderr:`n");
    [Console]::Write($Meta2);
    [Console]::Write("`n");
    $Meta3=""
    foreach ($el in $r.Meta3){
        $Meta3+=$el
    }
    $Meta3=($Meta3 -split "[`r`n]") -join "`n"
    $Meta3=($Meta3 -split "[`n]{2,}") -join "`n"
    [Console]::Write("stdout:`n");
    [Console]::Write($Meta3);
    [Console]::Write("`n");
    

    【讨论】:

      猜你喜欢
      • 2010-10-14
      • 2014-07-22
      • 2015-06-21
      • 1970-01-01
      • 1970-01-01
      • 2012-08-07
      • 1970-01-01
      • 2022-01-18
      • 1970-01-01
      相关资源
      最近更新 更多