Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2042658
  • 博文数量: 519
  • 博客积分: 10070
  • 博客等级: 上将
  • 技术积分: 3985
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-29 14:05
个人简介

只问耕耘

文章分类

全部博文(519)

文章存档

2016年(1)

2013年(5)

2011年(46)

2010年(220)

2009年(51)

2008年(39)

2007年(141)

2006年(16)

我的朋友

分类: WINDOWS

2010-05-28 17:49:39

 什么是二次重定向呢? >nul 2>nul 就是一个典型的二次重定向。一般情况下,二次重定向不会有问题产生,但也有例外,例如:

echo. 2>nul 3>nul
执行这个命令后,所有出错误提示均看不到了

echo. 1>nul 3>nul
执行这个命令后,所有的输出提示均看不到了(但是错误提示会显示)?
这两个命令却无法同时使用。

 

  还有执行以下语句后将会一直循环显示,无法停上:
echo. 0>nul 3>nul


  另外:

echo. 2>nul 3>test.txt
以后就会将出错信息写入到test.txt中.
同理,
echo. 1>nul 3>test.txt
就会将标准输出信息写入到test.txt中.


  为什么会这样呢?

 

  这确实是一个有意思且有意义的主题。关于这个奇怪的现象,因为未见于公开的官方文档,所以它似乎是介于未公开特性与程序算法漏洞之间的存在。

  经过简单测试得到以下结论:

  这个现象由句柄二次重定向所引起,与语句的命令主体无关;
  二次重定向的目标可以不同,前次重定向影响本语句,后次重定向影响语句结束后的CMD环境;
  后次重定向的句柄必须是未定义句柄,且必须在前次重定向之前未曾使用过;此次使用后即刻作废,不可重复用于缺省CMD环境的句柄重定向;

  由此我对此现象的推测如下:

  在CMD中的某一语句中实现句柄的修改(重定向或者复制)时,设计者为了实现在语句执行完后,恢复被修改的句柄,则必然会在修改之前复制(或者说备份)句柄,至于备份的目的地,CMD选择了从未曾使用过的“未定义句柄(3-9)”,这似乎是一个无可厚非的选择。但是程序在判断并获取未使用句柄时显然存在某些漏洞,它们首先处理第一个修改操作,在得到要修改的句柄后,立即寻找未使用的备份句柄,在找到备份句柄并进行备份后,才处理随后的修改操作,而此时这个备份句柄仍然可以被修改,导致在语句结束后,CMD会使用修改后的备份句柄恢复第一次修改的句柄,最后导致CMD的缺省句柄被修改。而此时CMD才得知备份句柄已被使用,而会在下一语句中修改句柄时使用其后的“未使用句柄”进行备份。

  以下的语句应该也是类似的原理,只是更加准确的说明了获取备份句柄的时机。

pause 1>&3 3>nul

  所以,CMD帮助文档中关于3-9是未定义句柄的说辞,应该是不够准确的,因为它确实会被系统移作他用,而并非“由应用程序单独定义,它们是各个工具特有的”,由此看来,它更像是“保留句柄”。

  另外,CMD中句柄的行为显然更为复杂了,尤其是句柄复制的行为,即使微软的文档对此也是语焉不详。比如以下的语句可以将stdout复制到stderr,而stderr被重定向到了nul设备,结果导致pause的stdout重定向到nul设备,也即无输出。这是可理解的。

pause 2>nul 1>&2

  而在下面的语句中,仅仅将复制与重定向的操作反转,便不再有效。而这也应与以上提到的CMD特性有关。

pause 1>&2 2>nul


  最后需要提及的是,CMD中句柄具有读写属性,stdin是只读的,stdout是只写的,stderr是可读可写,其它未见定义。复制句柄的同时,也复制了句柄的读写属性。

 

阅读(2147) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~