为了技术,我不会停下学习的脚步,我相信我还能走二十年。
分类:
2012-07-06 20:27:16
原文地址:那些我自己了解的重定向 作者:g_programming
那些我自己了解的重定向
在学习shell的时候,重定向真的很重要,但是复杂一点的重定向就是太难搞懂了,我good 朋友在看《shell学习指南》161页的时候,问了我如下代码的意思:(以及书上的解释)
exec 5>&2 把原来的标准错误输出保存到文件描述符5上
exec 2> /tmp/test.log 重定向标准错误
...
exec 2>&5 将原始文件复制到文件描述符2
exec 5>&- 关闭文件描述符5
在这里我就想,当有如下语句的时候:注意shell在处理重定向的时候都是由左至右
(1)make > res 2>&1,> res标准输出重定向到了res文件,标准错误没有处理,2>&1标准错误重定向到了标准输出,但是此时标准输入以及重定向到了res,所以标准错误也重定向到文件;
标准输出=标准错误=终端,标准输出=res,标准错误=标准输出,所以:标准输出=标准错误=res
(2)make 2>&1 > res ,2>&1标准错误输出到标准输出,所以标准错误输出,但是标准输入没有处理,> res标准输出重定向了到res文件中,因此,标准错误输出和标准输出不在同一个文件
标准输出=标准错误=终端,标准错误=标准输出,标准输出=res,所以:错误信息在终端,标准输出在res
既然make > res 2>&1 是将标准错误重定向标准输出,那么我想exec 5>&2也是将文件描述符5重定向到标准输出,但是实际上这么理解是错误的,我们来看如下执行的命令顺序:
$exec 5>&2 #作用现在未知
$exec 3>/tmp/test.log #以文件描述符3打开文件
$echo ‘test1’1>&5 #将标准输出重定向到文件描述符5,
test1 #我们可以发现直接输出到了终端上,由于标准错误和标准输出都会输出到终端上,我们#这里可以知道,’test1’输出到文件描述符5上就是输出到了文件描述符2上
$echo ‘test2’1>&3 #没有输出到终端上,’test2’输出到了文件/tmp/test.log中
$cat /tmp/test.log
test2
$echo ‘test3’ 3>&1 #由于echo是打印到标准输出的,所以重定向3到1想到于没有作用
test3
$cat /tmp/test.log #测试/tmp/test.log,结果正如上而言,文件/tmp/test.log内是原内容
test2
$echo ‘test4’>&5 #文件描述符5为标准错误
test4
$exec ‘test5’>&2 #文件描述符2为标准错误
test4
$exec 2> /tmp/test1.log #以文件描述符2打开文件,注意这样打开会在终端卡死,请在脚本测试
$echo ‘test’ >&2 #输出’test’到文件描述符2,没有输出到终端,说明文件描述符2已经改变
$cat /tmp/test1.log #/tmp/test1.log的文件内是写到文件描述符2的内容
test
$echo ‘test’ >&5 #输出到终端,现在文件描述符5就是标准错误
test
通过测试可以知道:
(1) exec 5>&2,文件描述符5以只写的方式打开文件描述符,并且将原来标准错误的输出也输出到文件描述符5上,我们可以将它看作以文件描述符5打开了标准错误文件,所以echo ‘test’ >&2和echo ‘test’ >&5的作用一样;
(2) exec 2> /tmp/test1.log,文件描述符2以只写的方式打开文件,那么文件描述符2不再是标准错误,而是打开/tmp/test1.log的文件描述符;
(3) exec 2>&5,以文件描述符2以只写的方式打开了文件描述符5所指代的文件,当前文件描述符5是指向标准错误的,所以文件描述符2重新得到了标准错误的文件描述符;
(4) make > res 2>&1,重定向,将标准错误的输出输出到标准输出;
(5) exec 5>&-和exec 5<&-将文件描述符读写端都关闭;