请想象一下,我有两个主stream输出的程序:err && out。 作为一个例子,我们可以使用下一个bat文件:
@echo off echo 1 echo 2 >&2 echo 3 echo 4 >&2 echo 5 echo 6 >&2 echo 7 echo 8 >&2 echo 9 echo 10 >&2
所以在控制台的屏幕上,我会看到这个输出:
1 2 3 4 5 6 7 8 9 10
我想看看这个输出! 完全如我所料。 但是我也想在一些特定的“ERR.out”文件中同时看到整个errstream。 所以它的内容考虑到我的最初的蝙蝠文件应该是:
2 4 6 8 10
所以我的问题是 – 如何在BAT文件的情况下为Windows XP SP3做这个技巧?
我想使用下一个伪代码 – 但它当然不会工作。 但是我希望主要的逻辑是一样的:command.exe | print_it_as_is_on_screen | redirect_2_stream_to_ERR.out_file | send_whole_output_to_another_command.exe
我相信不可能做到你想要的。 下面是我的原始答案,不起作用,然后是一个可以工作的修改,但不能保证在所有情况下工作,然后解释为什么不能完美地完成。
有2个部分来解决你的问题。
首先 ,您需要一个可以读取stdin并将其写入stdout和文件的tee程序。 您可以从gnuwin32 CoreUtils for Windows使用tee.exe,也可以使用以下混合JScript /批处理文件 – TEE.BAT
@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment ::--- Batch section within JScript comment that calls the internal JScript ---- @echo off cscript //E:JScript //nologo "%~f0" %* exit /b ----- End of JScript comment, beginning of normal JScript ------------------*/ var fso = new ActiveXObject("Scripting.FileSystemObject"); var mode=2; if (WScript.Arguments.Count()==2) {mode=8;} var out = fso.OpenTextFile(WScript.Arguments(0),mode,true); var chr; while( !WScript.StdIn.AtEndOfStream ) { chr=WScript.StdIn.Read(1); WScript.StdOut.Write(chr); out.Write(chr); }
确保tee.exe或tee.bat在您当前的文件夹中,或者在您的路径中的某处。
然后,您可以将您的批处理脚本的输出管道化为如下所示:
yourBatch | tee output.txt
但管道操作捕获标准输出并将其重定向到第二个程序。 因此,上面的代码会捕获output.txt中的stdout,但是您想要捕获stderr。
其次 ,你需要一个交换stdout和stderr的机制。 这是令人惊讶的简单:-)
yourBatch 3>&2 2>&1 1>&3 | tee err.txt
我描述了如何在我接受的答案上面的工作是否有一种方法来重定向只stderr标准输出(不结合这两个),所以它可以管道到其他程序?
以上不起作用:-(
有多个计时问题,以防止上述工作正常。 第一个问题是在tee准备处理输入之前有一个启动时间。 批处理文件(或其他任何进程)可以将交织消息写入stdout和stderr,stderr通过管道发送,而stdout直接进入控制台。 stdout会立即转发到控制台,但stderr会延迟,而tee会准备输入和输出流。 在测试用例中,在开始写入控制台之前,整个stdout内容都会写入控制台。 所以控制台输出看起来像
1 3 5 7 9 2 4 6 8 10
我能够通过使用额外的批处理脚本延迟启动程序,直到三通完成初始化,在Win 7和XP虚拟机上都能得到正确的输出。 这只适用于gnu tee.exe。 它不能与tee.bat可靠地工作。
首先,我在与测试文件夹相同的文件夹中创建delay.bat。
@echo off ping 192.0.2.2 -n 1 -w 1000 >nul %*
然后下面的命令在我的机器上给出正确的结果
delay.bat test.bat 3>&2 2>&1 1>&3 | tee.exe err.txt
如果我用tee.bat替换tee.exe,结果是不可重复的。 即使使用tee.exe,也可能无法在其他机器上运行。
偶尔tee.bat产生正确的输出,但通常其中一个数字被丢弃,否则某些stdout和stderr输出合并成一行。 它不可靠的原因与更微妙的时间问题有关。
原来的程序写stdout和stderr到控制台就好了,因为它是一个进程控制(写)每一个。 这个过程一次只能写一个东西。 但是当stderr连接到TEE时,有两个进程试图同时写入控制台。 TEST.BAT正在写stdout,而TEE正在写stderr。 没有什么能阻止混合在一起的同时写入,导致混合输出。 我想要得到真正的同时写入机器必须有多个CPU,或至少多个核心。 但即使是一台CPU机器也可能有问题,因为没有办法保持两个进程同步。 即使输出不混合,也很容易失灵。
即使tee.exe在我的机器上工作,我怀疑甚至可能会失败,无论是不同的源输入,或者在另一台机器上。
我相信不可能得到你的结果。 您可以将stderr重定向到stdout,并将两个管道都连接到tee。 这将保持控制台输出正常,但是无法从标准输出中分离stderr输出。
唯一能够可靠地获得结果的方法是修改源代码,将每条错误消息写入两个流。 但是当你的源头不在你的控制之下时,这是不可能的。