gpt4 book ai didi

windows - 将 stderr 重定向到文件,但保持屏幕上的所有输出完好无损 (as_is)。 [Windows XP - BAT 文件]

转载 作者:可可西里 更新时间:2023-11-01 14:04:42 25 4
gpt4 key购买 nike

请想象一下,我有一些程序在两个主要流中都有输出: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”文件中同时看到整个 err 流。
所以考虑到我的初始 bat 文件的内容应该是:
2
4
6
8
10

所以我的问题是 - 如何在 BAT 文件的场景中为 Windows XP SP3 做那个技巧?

我想使用下一个伪代码 - 但它当然不起作用。但我希望主要逻辑是一样的:
命令.exe | print_it_as_is_on_screen | redirect_2_stream_to_ERR.out_file | send_whole_output_to_another_command.exe

最佳答案

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

有 2 个部分可以解决您的问题。

第一 ,您需要一个可以读取标准输入并将其写入标准输出和文件的 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

但是管道操作捕获标准输出并将其重定向到第二个程序。因此,上面的行将在 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 内容在 tee 甚至开始写入控制台之前写入控制台。所以控制台输出看起来像
1
3
5
7
9
2
4
6
8
10

通过使用额外的批处理脚本延迟启动程序,直到 T 恤完成初始化,我能够在 Win 7 和 XP 虚拟机上获得正确的输出。这仅适用于 gnu tee.exe。它不能与 tee.bat 一起可靠地工作。

首先,我在与 test 文件夹相同的文件夹中创建 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 时,有 2 个进程试图同时写入控制台。 TEST.BAT 正在写入 stdout,而 TEE 正在写入 stderr。没有什么可以阻止同时写入混合在一起,从而导致输出混淆。我想要获得真正的同时写入,机器必须有多个 CPU,或者至少有多个内核。但即使是单 CPU 机器也会出现问题,因为无法保持两个进程同步。即使输出没有混合,也很容易出现乱序。

即使 tee.exe 在我的机器上工作,我怀疑它甚至有可能失败,无论是使用不同的源输入,还是在另一台机器上。

我相信不可能可靠地得到你的结果。您可以将 stderr 重定向到 stdout,并将两者通过管道传输到 tee。这将使控制台输出保持直截了当,但是没有办法将 stderr 输出与 stdout 分开。

可靠地获得结果的唯一方法是修改源代码,从一开始就将每个错误消息写入两个流。但是当您的来源超出您的控制时,这是不可能的。

关于windows - 将 stderr 重定向到文件,但保持屏幕上的所有输出完好无损 (as_is)。 [Windows XP - BAT 文件],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16001386/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com