在Unix平台工作的人都使用过Shell的重定向功能,多数人接触较多的是简单的重定向,比如:
cmd > some_file 将cmd命令的标准输出重定向到some_file中
cmd < some_file 将some_file的内容作为cmd命令执行的标准输入,或者简单的说cmd命令从some_file读取输入

等等诸如此类的简单重定向还比较好理解的,起码从大于号或者小于号的箭头方向也可以感性的理解出来。但是类似Bash Shell中还有一些带有复杂符号的重定向功能,看起来就不那么直观了。

强记是不好的学习方式,加上个人理解的记忆才更牢固,使用起来才更为熟练。昨天晚上为了琢磨一个shell重定向命令,翻看相关bash shell重定向的资料,突然脑子里蹦出一个很容易理解的记忆shell文件描述符重定向的方法。

以“make 2>&1 1>build.log”为例,看起来挺头疼,符号增多了,加了一个'&'这个符号,有些晕。不能看表面,我们要看原理:打开“Unix环境高级编程(APUE)”中关于文件内核数据结构的说明,回顾一下,再对应上面的重定向命令。文件描述符重定向是什么?按照书中描述重定向就是进程文件描述符表项改变所指向的文件表项的操作。当make启动后,进程内部文件描述符表中元素1-> 文件表项1, 元素2->文件表项2,元素3 -> 文件表项3,三个文件表项又分别对应v节点表中的不同v节点。但是做了重定向后,"2>&1"将进程内部文件描述符表中的元素2指向文件表项1,与元素1指向相同,这时该进程文件描述符表中有两个文件描述符指向文件表项1了; "1>build.log"将进程内部文件描述符表中的元素1指向build.log对应的文件表项3。这样make执行过程中的标准输出会写入build.log中,而标准错误则会输出到屏幕上。

好了回顾完原理,再看看“make 2>&1 1>build.log”这个命令,'&'在C语言里是取地址的操作符,对应上面原理的描述,把&1看作是取1对应的文件表项;2>&1 则理解为将进程文件描述符表中元素2指向到元素1所对应文件表项上去。1>build.log理解为:将进程文件描述符表中元素1指向到元素3(build.log对应的文件描述符)所对应文件表项上去。这样理解起来就轻松多了。'<'也类似,cmd < som_file等价于cmd 0<some_file。

Shell平时用的不多,研究的也不多,所以用了这么多年才有这样粗浅的理解(这个理解也不一定通用,bash的重定向符号有太多,含义也有不一致),呵呵。

© 2009, bigwhite. 版权所有.

Related posts:

  1. “扶正”Bash Shell
  2. Unix Shell Scripting之'扫盲篇'
  3. CSCOPE使用中问题小解
  4. 也谈软件调试
  5. cmockery支持mock输出参数