读书人

求解惑Linux管道跟重定向

发布时间: 2013-01-08 14:02:14 作者: rapoo

求解惑,Linux管道和重定向
最近看到一篇关于管道的文章中有这样的描述:


alias testcmd='command ls -ld / xxx ~/.bashrc yyy'
# swap stdout & stderr stream, i.e.
# let the stderr stream pass through a pipe while the stdout is printed to the terminal only
# cf. http://tldp.org/LDP/abs/html/io-redirection.html:
# "Child processes inherit open file descriptors. This is why pipes work.
# To prevent an fd from being inherited, close it."
(
exec 3>&1
testcmd 2>&1 1>&3 3>&- | tr '[[:lower:]]' '[[:upper:]]' 3>&-
exec 3>&-
)

在我的RHEL上输出是这样的:
drwxr-xr-x 26 root root 4096 Oct 7 22:37 /
-rw-r--r-- 1 admin root 497 Aug 14 14:31 /home/admin/.bashrc
LS: XXX: NO SUCH FILE OR DIRECTORY
LS: YYY: NO SUCH FILE OR DIRECTORY

1>&3 3>&-这句,关闭3并不会导致1被block,由此可见,1>&3并不是一个套接的效果,而是一个赋值。也就是说,1->stdout, 运行1>&3之后,得到的是3->stdout,而不是1->3->stdout。那么问题是,2>&1 1>&3将导致1和2都指向stdout,bash如何鉴别谁需要进入管道?
我有一种猜想,就是因为有管道符的存在,所以testcmd 2>&1中的&1其实已经不再指stdout,而是作为tr命令的输入管道。大家觉得对么?元方,你怎么看?
[解决办法]
重定向其实是个文件描述符dup的过程,以你的例子而言:

testcmd 1>>log 2>&1
这个命令是先把log的文件描述符dup给fd1,此时fd1的文件表项指向的就是log文件,再把fd1 dup给fd2,这样fd2也指向了log文件

testcmd 2>&1 1>>log
这个命令先把fd1 dup给了fd2, 这样fd1和fd2的文件表项指向的都是终端设备,再把log的文件描术符dup给fd1,这样fd2仍然指向终端设备,fd1指向了log文件



引用:
感谢答复。我似乎明白了一些。但还是觉得有问题。
你在回复中也说"原来fd 1的内容被重定向到了fd 3",可见1出现在>的左右,是有不同的含义的。那么这个含义是什么呢?我试着将>左边的1理解成这个command的stdout,1理解成这个command的stderr,而>右边的1,2,3则表示这个process的fd。但这样的理解似乎也不对,因为众所周知改变重定向出现的……

读书人网 >UNIXLINUX

热点推荐