UPDATE:2014-4-1有点被搞晕了。。先随便写点,再慢慢更新。
1、有关I/O重定向
默认情况下始终有3个"文件(unix下一切皆为“文件”)"处于打开状态, stdin (标准输入), stdout (屏幕标准输出),stderr (屏幕标准错误输出)。这3个文件和其他打开的文件都可以被重定向。对于重定向简单的解释就是捕捉一个文件,命令,程序,脚本,或者甚至是脚本中的代码块的输出,然后将这些输出作为输入发送到另一个文件,命令,程序,或脚本中。我们常用"<"或">"就是将标准输入重定向或是标准输出重定向。
2、有关文件描述符
内核(kernel)利用文件描述符FD(file descriptor)来访问文件。文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。(来自百度百科的解释,感觉是不是类似于指针)。如stdin (标准输入), stdout (屏幕标准输出), stderr (屏幕标准错误输出)对应的文件描述符就是0、1、2,我们在简单地用 < 或 > 时,相当于使用 0< 或 1>
文件描述符 | 名称 | 常用缩写 | 默认值 |
0 | 标准输入 | stdin | 键盘 |
1 | 标准输出 | stdout | 屏幕 |
2 | 标准错误输出 | stderr | 屏幕 |
将I/O重定向到文件描述符的常用表达式:
i>&j
重定向文件描述符i 到j。
指向i 文件的所有输出都发送到j中去。
>&j
默认的,重定向文件描述符1(stdout)到j。所有传递到stdout的输出都送到j中去。我们常用的:
2>&1 #将标准错误输出到1
0< FILENAME
< FILENAME
从文件中接受输入。 ">"是成对命令,并且通常都是结合使用。
[j]<>filename
把文件打开并且分配文件描述符"j"给它,即给一个打开文件赋予文件描述符(给它标一个指针?)。如果文件"filename"不存在,那么就创建它,。如果文件描述符"j"没指定,那默认是fd 0, stdin。
#command < input-file > output-file
关闭文件描述符:
n<&- 关闭输入文件描述符n
0<&-, <&- 关闭stdin
n>&- 关闭输出文件描述符n
1>&-, >&- 关闭stdout
附上一段代码帮助理解:
echo 1234567890 > File# 写字符串到"File".exec 3<> File # 打开"File"并且给它分配fd 3.read -n 4 <&3# 只读4个字符.echo -n . >&3# 写一个小数点.exec 3>&-# 关闭fd 3.cat File # ==> 1234.67890 # 随机存储.
思考题:
1、ls -yz >> command.log 2>&1和 ls -yz 2>&1 >> command.log 的区别?
答:1)前者能正确将FD2输出到FD1,即标准错误指向标准输出,即,这个两个输出都写入command.log中,而后者则不能,只会将标准输出写入command.log,而错误输出则打印到屏幕上,即错误输出没有跟随标准输出一同写入comman.log。
2)stdout是行缓存的输出,而stderr是非缓冲的错误流输出, ls -yz 2>&1 >> command.log,此时”2>&1“,系统将会把错误输出转化成标准输出并打印在屏幕而不是写入到后面的 >>command.log。
(这一段有点拗口,需要明白stderr是一种错误,当“2>&1”时,stderr将变成标准输出,不再是一种错误)
2、可以使用普通用户运行以下命令来进行体会:
du -m /var 1>dev/null|grep yum#将标准输出关闭,(直接使用1>&-关闭会生效但是报bad的FD,2>&-不会报,应该是命令把错误输出关掉以致报错也没有了)。此时屏幕只#有错误输出,grep命令不会生效。du -m /var 2>&1 1>/dev/null |grep yum#此时屏幕会以标准1输出错误输出,同时grep “yum”字符。再次验证了stderr是非缓冲流输出。