入门:
stdout, stdin, stderr的中文名字分别是标准输出,标准输入和标准错误。
在Linux下,当一个用户进程被创建的时候,系统会自动为该进程创建三个数据流,也就是题目中所提到的这三个。那么什么是数据流呢(stream)?我们知道,一个程序要运行,需要有输入、输出,如果出错,还要能表现出自身的错误。这是就要从某个地方读入数据、将数据输出到某个地方,这就够成了数据流。
因此,一个进程初期所拥有的这么三个数据流,就分别是标准输出、标准输入和标准错误,分别用stdout, stdin, stderr来表示。对于这三个数据流来说,默认是表现在用户终端上的,比如我们在c中使用fprintf:
fprintf(stdout, "hello world!\n");
屏幕上将打印出"hello world!"来,同样,我们使用:
上面的代码会接收用户输入在终端里的字符,并存在ptr中。
fread(ptr, 1, 10, stdin);
那么标准输入输出和错误是不是只能反应在终端里呢?答案是不是的!我们可以将标准输入和输出重定位到文件中:
例如,我们使用ls命令,会把当前目录下的文件名输出到终端上:
$lsgcc gcc.sh gmp-5.0.1 gmp-5.0.1.tar.bz2 linux-loongson-community-2.6.35-rc1 longene-0.3.0-linux-2.6.34 mpfr-3.0.0 mpfr-3.0.0.tar.gz oprofile-0.9.6
我们可以使用 “ > ”符号,将ls的标准输出重定向到文件中:
$ls > lsout //将标准输出重定向为文件lsout$more lsout //显示lsout文件里的内容gcc gcc.sh gmp-5.0.1 gmp-5.0.1.tar.bz2 linux-loongson-community-2.6.35-rc1 longene-0.3.0-linux-2.6.34 mpfr-3.0.0 mpfr-3.0.0.tar.gz oprofile-0.9.6
同样,我们也可以使用“ < ”符号将标准输入重定向到文件中,以sort为例,以下示例使用 sort 命令对由键盘键入的文本进行排序。键入ctrl-D 结束标准输入。终端屏幕显示的标准输出如下:
$sortmuffyhappybumpyCTRL-D // 结束标准输入。 bumpyhappymuffy //结束标准输出。
使用" < "重定向后为:
$ more socks 显示 socks 的内容。polka dotargyleplaid $ sort < socks 将输入重定向为从 socks 输入,并将内容排序。argyleplaidpolka dot
进阶:
#man bash 里面有一段有关重定向的描述:
Note that the order of redirections is significant. For example, the
command
ls > dirlist 2>&1
directs both standard output and standard error to the file dirlist,
while the command
ls 2>&1 > dirlist
directs only the standard output to file dirlist, because the standard
error was duplicated as standard output before the standard output was
redirected to dirlist.
辗转各个社区,终于算是略微明白了一点。
上面第一条命令:#ls >dirlist 2>&1
把标准输出(STDOUT,1)和标准错误(STDERR,2)都重定向到文件 dirlist 的过程如下:
0 命令执行前
(此时:STDOUT指向终端、STDERR 也指向终端)
1 建立名为 dirlist 的空文件
2 执行 > dirlist
(因为 > 默认为重定向 STDOUT ,即该步骤将 STDOUT 重定向为 文件dirlist)
(此时:STDOUT指向 文件dirlist、STDERR 指向终端)
3 执行 2>&1 ,简单的说,就是 STDERR 变得和 STDOUT 一样。换句话说,就是把 STDERR 重定向为 “STDOUT 所指向的东西”
(因为之前 STDOUT 已经指向了 文件dirlist,所以执行到该步骤时,STDERR 也重定向到了 文件dirlist)
(此时:STDOUT指向 文件dirlist、STDERR 也指向 文件dirlist)
4 执行 ls,则由于执行 ls 所产生的标准输出和标准错误信息都被输出到了 文件dirlist 里面。
上面的第二条命令:#ls 2>&1 > dirlist
仅仅把标准输出重定向到了 文件dirlist中(标准错误依然是终端)
我们依然一步一步走,看看为什么:
0 命令执行前
(此时:STDOUT指向终端、STDERR 也指向终端)
1 建立名为 dirlist 的空文件
2 执行 2>&1
(因为原来 STDOUT 和 STDERR 都指向终端,所以相当于,把 STDERR 从终端,重定向为终端……)
(此时:STDOUT指向终端、STDERR 也依然指向终端)
3 执行 > dirlist,把 STDOUT 重定向为 文件dirlist
(此时:STDOUT指向 文件dirlist、STDERR 依然指向终端)
4 执行 ls,那么,产生的 STDOUT 输出到了 文件dirlist里面,而 STDERR 输出到了终端
另外,要将 STDOUT 和 STDERR 都输出到文件,也可以这么写:
#ls &> dirlist
这样还比较方便一点。
关于 2>&1位置的问题:
$ cat cities > cities.copy 2>&1
...writes both stderr andstdout tocities.copy
be careful about this:
$ cat cities 2>&1 > cities.copy
...writes stderr to/dev/tty andstdout tocities.copy
以下是相关讨论的地址:
http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-3.html#ss3.2
http://bbs.chinaunix.net/viewthread.php?tid=16361
http://www.linuxsir.com/bbs/showthread.php?threadid=38203
http://www.linuxsir.com/bbs/showthread.php?threadid=40501&highlight=%D6%D8%B6%A8%CF%F2