为什么我的stderr重定向在命令完成后没有结束?我该如何解决?

Erb*_*ert 24 windows command-line cmd batch-file

在Windows中,无论是在命令行还是批处理文件中,命令"DIR 2> NUL:3>&2"(您可以将任何内容替换为"DIR",即使不是文件或命令)也会产生所有错误然后失踪,除非你在每个命令后写"2> CON:".为什么CMD甚至会这样做?如何在不启动新的CMD流程的情况下恢复正常?"DIR 2> CON:3>&2"仅适用于该命令.

编辑:这也适用于文件."DIR 2> TEXT.TXT 3>&2"之后的任何错误都将附加到文件中.

dbe*_*ham 31

这是一个测试脚本,可以重现您遇到的问题.

@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
Run Code Online (Sandbox Code Playgroud)

这是输出

I want to see stream1
stream1 works fine
stream3 works fine
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

这是所需的输出:

I want to see stream1
stream1 works fine
stream2 works fine
stream3 works fine
Run Code Online (Sandbox Code Playgroud)

我真的不明白发生了什么.但我做了一些有趣的实验.看看这个帖子: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
Run Code Online (Sandbox Code Playgroud)

更新2012-04-03 我相信我终于明白了Windows CMD.EXE重定向的机制.我有一个充分考虑所有奇怪行为的工作理论,包括为什么反转命令会阻止"永久"重定向.它还解释了Aacini的观察,即句柄3似乎与CON连接:(实际上,根据Windows文档,它实际上是未定义的).

关键点是:

1 - 每当重定向句柄(流)时,原始定义将转移到第一个可用的未定义句柄.连续重定向始终从左到右执行.

2 - 重定向结束时,通常会恢复原始定义.但是如果存在一系列重定向,那么恢复只能做到1级深度.这是"永久"重定向的来源.

编辑2014-12-19:换句话说,恢复似乎是使用队列结构(FIFO - 先进先出)完成的,当它应该被实现为堆栈(LIFO - 后进先出).

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

完整的理论和测试用例可在http://www.dostips.com/forum/viewtopic.php?p=14612#p14612上连续发布两篇文章.

  • +5,(如果可以的话),这是一个非常令人印象深刻的流媒体机制分析,它的工作原理并不是很明显 (4认同)
  • 谢谢,这很有效,给我+1!但我自己进行了一些实验,使用颠倒顺序(2之前的3)似乎工作并且比你的例子更容易:"FILE.BAT 3> NUL:2>&3". (2认同)

Mar*_*som -2

问题在于3>&2. 文件描述符 3 无效,并且它似乎在某种程度上扰乱了 Windows。放下它吧,你不需要它。

请参阅Microsoft 的文档(已存档)以了解完整的处理方法。