为什么我的stderrredirect在命令完成后结束? 我该如何解决?

Windows中,无论是在命令行还是batch file中,命令“DIR 2> NUL:3>&2”(即使不是文件或命令,也可以用“DIR”代替任何文件或命令)那么除非你在每一个命令后都写上“2> CON:”。 为什么CMD甚至做到这一点? 如何在不开始新的CMD过程的情况下恢复正常? “DIR 2> CON:3>&2”仅适用于单独的命令。

编辑:这将与文件一起工作。 “DIR 2> TEXT.TXT 3>&2”之后的任何错误都会附加到文件中。

Solutions Collecting From Web of "为什么我的stderrredirect在命令完成后结束? 我该如何解决?"

这是一个测试脚本,可以再现您所看到的问题。

@echo off 2>nul 3>nul ( echo I want to see stream1 1>&2 echo I don't want to see this stream2 1>&3 echo I don't want to see this stream3 ) echo stream1 works fine 1>&2 echo stream2 is now "permanently" void. I don't see this. 1>&3 echo stream3 works fine 

这里是输出

 I want to see stream1 stream1 works fine stream3 works fine 

stderr(流2)已被“永久”禁用,即使对于父CMD.EXE shell。

您可以通过分阶段进行重定向来避免“永久”方面:

 @echo off 2>nul ( 3>nul ( echo I want to see stream1 1>&2 echo I don't want to see this stream2 1>&3 echo I don't want to see this stream3 ) ) echo stream1 works fine 1>&2 echo stream2 works fine 1>&3 echo stream3 works fine 

这里是所需的输出:

 I want to see stream1 stream1 works fine stream2 works fine stream3 works fine 

我真的不明白是怎么回事。 但是我做了一些有趣的实验。 看看这个主题: http : //www.dostips.com/forum/viewtopic.php? f=3& t= 2836& start=30

附录

正如Erbert在他的评论中发现和分享的那样,如果您只是切换重定向的顺序,那么修复就更容易了 – 无需分级。

 @echo off 3>nul 2>nul ( echo I want to see stream1 1>&2 echo I don't want to see this stream2 1>&3 echo I don't want to see this stream3 ) echo stream1 works fine 1>&2 echo stream2 works fine 1>&3 echo stream3 works fine 

更新2012-04-03我相信我终于明白了Windows CMD.EXE重定向的机制。 我有一个工作理论,充分说明了所有怪异的行为,包括为什么颠倒顺序阻止“永久”的重定向。 这也解释了Aacini的观察,即句柄3似乎与CON连接:(不是,根据Windows文档,它实际上是未定义的)。

关键是:

1 – 每当一个句柄(流)被重定向时,原来的定义被转移到第一个可用的未定义句柄。 连续的重定向总是从左到右进行。

2 – 重定向结束后,通常会恢复原始定义。 但是,如果有一连串的重定向,那么修复只能进行1级。 这是“永久”重定向的来源。

编辑2014年12月19日:换句话说,恢复似乎是使用队列结构(先进先出先进先出),当它应该被实现为一个堆栈(LIFO – 后进先出)。

3 – CMD.EXE执行重定向时,首先将当前定义保存在未定义的句柄中,然后重定向第一个句柄。 如果第一个句柄被重定向到最初未定义的句柄,那么它被有效地重定向到它的原始定义! 这就是为什么echo hello 1>&3输出到控制台。

完整的理论和测试案例可以在http://www.dostips.com/forum/viewtopic.php?p=14612#p14612连续两篇文章中找到 。

我道歉发布这个答案,而不是一个评论,但我的“评论”太大…

在MS-DOS标准中,所有正在运行的程序都打开了这些标准句柄 :0-STDIN(键盘),1-STDOUT(屏幕),2-STDERR(屏幕),3-STDAUX(串口)和4-STDPRN(打印机)。 虽然Windows文档清楚地表明句柄3-9是未定义的,但句柄3通过CMD.EXE有特殊的处理。 我有三个理由想这个:

1-手柄3连接到CON:设备(键盘用于输入,屏幕用于输出); 句柄4-9不:

 C>ver Microsoft Windows XP [Version 5.1.2600] C>echo To handle 3 >&3 To handle 3 C>echo To handle 4 >&4 The handle could not be duplicated during redirection of handle 1. C>set /P var=From handle 3: <&3 From handle 3: Value entered in keyboard C>echo %var% Value entered in keyboard C>set /P var=From handle 4: <&4 The handle could not be duplicated during redirection of handle 0. 

2-本专题中的句柄3的奇怪行为,是以两种不同的方式解决的。 我发现,如果句柄0,1或2被重定向到句柄3(可能是句柄4-9),则句柄0,1或2的重定向将变为“永久”。 如果句柄0,1或2是包含句柄3的重定向列表中的最后一个句柄,则不会发生此行为。如果句柄0,1或2被重定向到句柄4-9,则完全避免此问题以任何顺序,但不处理3。

3-我的TypeOfHandle.com程序获得的结果。 这个程序是一个纯粹的MS-DOS可执行文件,它检查参数中给出的句柄,如果句柄连接到CONsole设备,则通过errorlevel返回值3;如果句柄被重定向到磁盘文件,则返回值128 。 这是结果:

 C>typeofhandle 0 C>echo %errorlevel% 3 C>typeofhandle 0 < anyFile.txt C>echo %errorlevel% 128 C>typeofhandle 1 C>echo %errorlevel% 3 C>typeofhandle 1 > anyFile.txt C>echo %errorlevel% 128 C>typeofhandle 3 C>echo %errorlevel% 0 C>typeofhandle 3 <&3 anyFile.txt C>echo %errorlevel% 0 C>typeofhandle 3 >&3 anyFile.txt C>echo %errorlevel% 0 

处理3-9在其他方面表现奇怪:

我的SetFilePointer.com程序获得的结果。 虽然在批处理文件中可以使用句柄3-9来实现一次输入/输出多个文件,但这种机制只允许顺序访问,因为我的SetFilePointer程序不能移动句柄3-9的文件指针。 SetFilePointer程序正确地在句柄0,1和2上工作; 此功能允许在批处理中编写完整的关系数据库应用程序。 这个主题在这篇文章中有详细描述

问题是3>&2 文件描述符3是无效的,它似乎以某种方式扰乱Windows。 离开它,你不需要它。

请参阅Microsoft的文档以获得完整的处理。