我有一个写入错误输出的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相关的调试文本。
答案 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