Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将sterr重定向到文件,但保留屏幕上的所有输出不变(按原样)。[windows XP-BAT文件]_Windows_Redirect_Batch File_Stdout_Stderr - Fatal编程技术网

将sterr重定向到文件,但保留屏幕上的所有输出不变(按原样)。[windows XP-BAT文件]

将sterr重定向到文件,但保留屏幕上的所有输出不变(按原样)。[windows XP-BAT文件],windows,redirect,batch-file,stdout,stderr,Windows,Redirect,Batch File,Stdout,Stderr,请想象一下,我有一个程序,它在两个主流中都有输出: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。 例如,我们可以使用下一个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文件的场景中,如何在WindowsXPSP3上实现这一技巧

我想使用下一个伪代码——但它当然不会工作。但我希望主要逻辑是相同的: command.exe |在屏幕上按原样打印|重定向|流|到| ERR.out |文件|发送|整个|输出|到|另一个| command.exe

我相信不可能可靠地完成您想要的任务。下面是我的原始答案,它不起作用,然后是可能起作用的修改,但不能保证在所有情况下都能起作用,然后解释为什么不能完美地完成修改。

有两个部分可以解决你的问题

首先,您需要一个tee程序,可以读取stdin并将其写入stdout和文件。您可以从中使用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。这非常简单:——)

我在接受的答案中描述了上述工作原理

上述操作无效:-(

存在多个计时问题,这些问题会妨碍上述程序正常工作。第一个问题是在tee准备好处理输入之前有一个启动时间。批处理文件(或任何进程)可以向stdout和stderr写入交错消息,stderr通过管道传输到tee,stdout直接发送到控制台。stdout会立即转发到控制台,但在tee准备输入和输出流时,stderr会延迟。在您的测试用例中,整个stdout内容都会在tee开始写入之前写入控制台因此,控制台输出如下所示

1
3
5
7
9
2
4
6
8
10
我能够在Win 7和XP虚拟机上获得正确的输出,方法是使用额外的批处理脚本延迟启动程序,直到tee完成初始化。这仅适用于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.exe替换tee.bat,结果将不可复制。即使使用tee.exe,它也可能无法在其他计算机上工作

偶尔tee.bat会生成正确的输出,但通常会删除其中一个数字,或者将一些stdout和stderr输出合并为一行。其不可靠的原因与更微妙的计时问题有关

原始程序将stdout和stderr都写入控制台,因为它是一个进程控制(写入)每次。进程一次只能写一件事。但是,当stderr通过管道传输到TEE时,则有两个进程试图同时写入控制台。TEST.BAT正在写入stdout,TEE正在写入stderr。没有任何方法可以阻止同时写入混合,从而导致混合输出。我想得到truly同时写入机器必须有多个CPU,或至少有多个内核。但即使是单CPU机器也可能有问题,因为无法使两个进程保持同步。即使输出没有混合,也很容易出现故障

尽管tee.exe可以在我的机器上运行,但我怀疑它甚至有可能失败,无论是使用不同的源输入,还是在另一台机器上

我认为不可能可靠地获得结果。您可以将stderr重定向到stdout,并将两者都通过管道传输到tee。这将保持控制台输出的直线性,但是无法将stderr输出与stdout分开


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

Imo这不能成批工作。您只能有一个输出流。请查看
tee
或类似的Windows Unix工具。nope-it不按我所希望的那样工作。在这种情况下,屏幕上的主要输出将是:
1 3 5 7 9 2 4 6 8 10
另外-它不允许在输入另一个command.exe时进一步发送整个输出。因此-再次-主要思想是=不要破坏main command.exe的输出物理顺序-以某种方式同时将所有stderr流复制到special文件,允许发送整个输出(stderr+stdout)|或仅发送选定的一个(例如,stderr或stdout)在管道上执行下一个命令。exe@graphElem-我明白了问题所在。我添加了一个可能的解决方案,但并不总是可靠的,但没有完美的解决方案。我会在得到时间后添加更多解释。不-再次说明它不起作用。相同的错误输出+加上非常明显的延迟。我从MinGW安装中获得的tee.exe。另外-看起来我可以不要直接向另一个程序发送输出:delay.bat test.bat 3>&22>&11>&3 | tee.exe err.txt | win|iconv.exe-c-f UTF-8-t CP866生成的结果-不好。另外,有时(我尝试了10次)我会得到更多不可用的输出:`1 2 3 4 5 7 8 10`愚蠢的规则r
delay.bat test.bat 3>&2 2>&1 1>&3 | tee.exe err.txt