将“标准错误”更改为“标准输出”

时间:2011-05-28 18:09:44

标签: powershell stdout stderr

我有一个写入错误输出的PowerShell脚本。脚本可以像下面这样简单:

Write-Error 'foo'
Start-Sleep -s 5
Write-Error 'bar'

我实际调用的脚本会生成一个外部进程,需要一段时间才能处理并写入标准错误。

现在当我像这样调用脚本时:

. myScript.ps1

我收到了PowerShell通常行为的错误消息(即红色文本和大量调试信息)。由于该文本在我的实际应用程序中与PowerShell无关,因此我不需要那些调试信息,只会降低结果的可读性(并且无法处理)。

有没有办法将输出直接重定向到标准输出,这样我才能得到文本?

我试过这样的事情:

Write-Host ( . myScript.ps1 2>&1 )

但这会延迟输出,直到一切都完成。

关于“调试信息”,当我立即运行脚本时,输出如下所示(红色):

C:\path\to\myScript.ps1 : foo
Bei Zeile:1 Zeichen:2
+ . <<<<  'C:\path\to\myScript.ps1'
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,myScript.ps1

C:\path\to\myScript.ps1 : bar
Bei Zeile:1 Zeichen:2
+ . <<<<  'C:\path\to\myScript.ps1'
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,myScript.ps1

当我使用Write-Host ( . myScript.ps1 2>&1 )运行脚本时,将错误输出写入标准输出,我得到如下结果:

foo bar

这正是我想要的输出,除了Write-Host (..)使输出仅在脚本终止后出现,所以我无法接收有关所述脚本进度的任何信息。

实际上更接近我的实际问题(因为用纯PowerShell很难解释这个问题);我有以下Python脚本,它类似于我使用的命令行程序,即它执行一些处理并将进度打印到标准错误:

#!/usr/bin/python
import sys, time
sys.stderr.write( 'Progressing... ' )
sys.stderr.flush()
time.sleep( 5 )
sys.stderr.write( 'done.\n' )
sys.stderr.flush()

现在,当我用python script.py调用它时,它正常工作并打印出“进度”行,等待5秒,然后将“完成”打印到PowerShell(作为普通文本)。现在的问题是我想在作业中运行 ,如下所示:Start-Job { python script.py }

作业正常启动,并且在后台工作正常,但是当我想通过Receive-Job <id>检查其进度时,我首先得不到任何输出,并且在脚本/程序完成后(即在5秒之后),我得到以下输出(再次为红色):

Progressing... done.
    + CategoryInfo          : NotSpecified: (Progressing... done.:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

显然,这不是我想要得到的。相反,我希望得到打印到标准错误的实际输出, live (即在脚本中发生时)和没有PowerShell相关的调试文本。

2 个答案:

答案 0 :(得分:3)

根据问题的编辑部分,这应该是合适的:

. MyScript.ps1 2>&1 | %{ Write-Host $_ }

它只写“foo”和“bar”,它们一出现就会出现。

修改

实际上这更简单,也可以正常工作:

. MyScript.ps1 2>&1 | Write-Host

但我保留原来的答案。该代码允许动态处理输出($_)并执行其他操作(即不只是将其写入主机)。

编辑2

写入STDERR的外部程序:

using System;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            for (int i = 0; i < 100; ++i)
            {
                Console.Error.WriteLine("Step " + i);
                System.Threading.Thread.Sleep(2000);
            }
        }
    }
}

将此应用程序作为作业启动并定期接收其输出的脚本。

$ErrorActionPreference = 'continue'

$job = Start-Job { C:\TEMP\Test\ConsoleApplication1.exe 2>&1 }
for(;;) {
    Receive-Job $job | Write-Host
    Start-Sleep 2
}

该脚本完全符合您的需要(对于您的编辑2 部分):它会在输出可用时立即显示输出,并且不会显示不需要的额外错误信息。

P.S。这个版本也有效:

$job = Start-Job { C:\TEMP\Test\ConsoleApplication1.exe }
for(;;) {
    Receive-Job $job 2>&1 | Write-Host
    Start-Sleep 2
}

答案 1 :(得分:1)

尝试:

$erroractionpreference = "silentlycontinue"
.\myscript.ps1