将stdout和stderr重定向到文件和控制台

7
在 PowerShell 脚本中,我调用一个程序,并希望将 stdoutstderr 重定向到 不同 的文件,同时仍然在控制台显示两者的输出。所以基本上,我想要......
stdout -> stdout
stdout -> out.log
stderr -> stderr
stderr -> err.log

到目前为止,我已经想出了这段代码,但不幸的是它只满足了要求1、2和4,标准错误没有显示在屏幕上。

& program 2>"err.log" | Tee-Object -FilePath "out.log" -Append | Write-Host

我如何将stderr打印到控制台呢?由于写入stderr会产生红色字体,因此我不想将stderr重定向到stdout,否则我将失去错误的视觉效果。

这不是与 https://dev59.com/pWAf5IYBdhLWcg3w2Fl6 重复了吗?您想立即将输出发布到控制台吗? - Clijsters
1
@Clijsters 当program运行时间较长时,产生一些中间输出可能会很有帮助。但尽管如此,这仍是一个不错的解决方法。 - SilverNak
1个回答

5

参考这篇博客文章,你可以编写一个自定义的tee函数,通过对象类型进行区分,并将内容写入相应的输出文件。代码如下:

function Tee-Custom {
    [CmdletBinding()]
    Param(
        [Parameter(
            Mandatory=$true,
            ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true
        )]
        [array]$InputObject,

        [Parameter(Mandatory=$false)]
        [string]$OutputLogfile,

        [Parameter(Mandatory=$false)]
        [string]$ErrorLogfile,

        [Parameter(Mandatory=$false)]
        [switch]$Append
    )

    Begin {
        if (-not $Append.IsPresent) {
            if ($OutputLogfile -and (Test-Path -LiteralPath $OutputLogfile)) {
                Clear-Content -LiteralPath $OutputLogfile -Force
            }
            if ($ErrorLogfile -and (Test-Path -LiteralPath $ErrorLogfile)) {
                Clear-Content -LiteralPath $ErrorLogfile -Force
            }
        }
    }
    Process {
        $InputObject | ForEach-Object {
            $params = @{'InputObject' = $_}
            if ($_ -is [Management.Automation.ErrorRecord]) {
                if ($ErrorLogfile) { $params['FilePath'] = $ErrorLogfile }
            } else {
                if ($OutputLogfile) { $params['FilePath'] = $OutputLogfile }
            }
            Tee-Object @params -Append
        }
    }
}

以下是该技术的使用示例:

& program.exe 2>&1 | Tee-Custom -OutputLogfile 'out.log' -ErrorLogfile 'err.log' -Append

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接