加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

将sterr重定向到文件,但保留屏幕上的所有输出(as_is). [Windows

发布时间:2020-12-14 03:53:28 所属栏目:Windows 来源:网络整理
导读:请假设我有一些程序在两个主流中都有输出:err出. 作为一个例子,我们可以使用下一个bat文件: @echo offecho 1echo 2 2echo 3echo 4 2echo 5echo 6 2echo 7echo 8 2echo 9echo 10 2 所以在控制台的屏幕上我会看到这个输出: 12345678910 我希望看到这个输出
请假设我有一些程序在两个主流中都有输出:err&&出.
作为一个例子,我们可以使用下一个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’文件中同时看到整个错误的流.
所以它的内容考虑到我的初始bat文件应该是:

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

解决方法

我相信不可能可靠地做你想做的事.下面是我原来的答案,它不起作用,然后是可能有效的修改,但不能保证在所有情况下都有效,然后解释为什么它不能完美地完成.

解决问题有两个部分.

首先,您需要一个可以读取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位于当前文件夹中,或者位于路径中的某个位置.

然后,您可以将批处理脚本的输出通过管道传输到tee,如下所示:

yourBatch | tee output.txt

但是管道操作捕获stdout并将其重定向到第二个程序.所以上面的行会捕获output.txt中的stdout,但是你想要捕获stderr.

其次,您需要一种机制来交换stdout和stderr.这非常简单:-)

yourBatch 3>&2 2>&1 1>&3 | tee err.txt

我在Is there a way to redirect ONLY stderr to stdout (not combine the two) so it can be piped to other programs?的答案中描述了上述内容的工作原理

以上不起作用:-(

存在多个时序问题,导致无法正常工作.第一个问题是在tee准备好处理输入之前有一个启动时间.批处理文件(或任何进程)可以将交错消息写入stdout和stderr,stderr通过管道连接到tee,stdout直接进入控制台. stdout会立即转发到控制台,但是当tee准备输入和输出流时,stderr会被延迟.在您的测试用例中,在开始写入控制台之前,整个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输出与标准输出分开.

可靠地获得结果的唯一方法是修改源代码,将每条错误消息写入两个流中.但是当你的资源不受控制时,这是不可能的.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读