Categories
bash [9]
Archives
February 2008 |
两个管道,两种处理guocongbin | 12/26 2007, 10:52
众所周知,一般的命令输出是可以输出到两个管道里面的。一个管道名曰标准输出(stdout,文件描述符为1)。另一个管道名为标准错误(stderr,文件描述符为2)。 通常来讲,stdout主要用来输出命令执行的结果;而stderr主要用来显示一些命令执行过程中的出错信息等等。 linux/unix中,我们可以使用带文件描述符的重定向符号来分别重定向输出到stdout和stderr的内容,例如 date >file1 2>file2 其中'>‘与'1>'等价,都意味著将输出到stdout的内容进行重定向。 关于这个重定向,另外一个典型的应用就是将 输出到stderr的内容屏蔽掉,也就是不显示错误信息。这个重定向的用法如下: cmd >file1 2>/dev/null /dev/null是一个特殊的设备,所有重定向到这里的内容都不会显示出来。
那么如何将输出到两个管道的内容写入同一个文件呢。这个其实很简单,这样写就可以。 cmd >file 2>&1 "2>&1"表示将stderr(2)重定向到stdout(1)。(但是,严格说来"2>&1"并不是这个意思,应该是将文件描述符2作为文件描述符1 的一个副本。)这样输出到两个管道的内容就合并到一起了。 有意思的是,上面写法的顺序是不可颠倒的,如果写成了 cmd 2>&1 >file 效果是与前者有着微妙的区别的。 现在我们做一个实验。 分别执行这两个命令,看看有什么结果输出 (echo aaaa; echo bbbb >&2) >file1 2>&1|cat (echo aaaa; echo bbbb >&2) 2>&1 >file1 |cat 我们可以看到第一条命令没有任何输出,因为所有的输出都已经重定向到文件file1中了。但是第二条命令却有输出,输出的内容是echo到stderr的内容。这是为啥呢? 这个其实可以如此解释。前面说过,"2>&1"并不表示将stderr重定向到stdout,而是将文件描述符2作为文件描述符1的一个副本。那么上面的第二条命令中,最开始的时候,文件描述符1和2 都没有被重定向,也就是都是输出到屏幕的。然后执行2>&1,这样文件描述符2成为了文件描述符1的副本,(注意,此时文件描述符1还是重定向到屏幕的);然后文件描述符1被重定向到文件file1中(注意,只有文件描述符1被改变了,它的原来的副本,也就是文件描述符2所代表的stderr管道并没有别修改)。如此一来,输出到stderr的内容就通过管道符号“|”传入到cat命令,作为输入了。 言归正传,本文的目的是提出一个解决如何处理输出到两个管道的内容。同时,输出的内容最终还要按照输出的顺序合并在一起。这个方法的一个应用场景就是log文件。比如,一个makefile的执行结果,输出的内容可能非常的多,因此想从里面找到编译错误信息就比较困难。如果我们能够自动的对输出到stderr的内容进行处理,那么我们就可以为这些内容做一些标记,方便其他程序对这个输出的log进行进一步的处理(比如做一个html的标签,使用特殊的字体或者颜色来显示stderr的信息)。 这个问题可以使用这个脚本来解决。 #!/bin/bash 上面的脚本的作用就是将输出到stderr的内容使用<B>和</B>扩起来(即,使用粗体显示)。输出的结果如下 aaaa 这样的一个脚本已经基本满足我们的需要了。 不过问题还是有的,例如我们要想分别同时处理输出到两个管道的内容,然后将处理的结果合并到一个文件里面。这该怎么办呢?在上面的方法中,只有一个管道的内容可以被一些命理处理,另外的一个管道的内容只能直接写入文件。因此上面的方法无法满足这个要求。 要解决这个问题,我们可以启动两个后台进程分别监听两个管道,如果管道内有内容写入,那么就读出内容,然后进行处理,然后写入到log文件中。示例脚本如下 #!/bin/bash 上面脚本中,首先创建两个管道pipe1 和pipe2,然后将文件描述符7和8关联到这两个管道。然后启动两个异步的进程,分别监听7和8。如果发现有内容写入7或者8,就进行相应的处理。凡是输出要进行这样处理的命令,都可以将stdout重定向到7上,stderr重定向到8上。 这样就大功告成了 Comments2 Responses to “两个管道,两种处理”2 Add comment |
Search
Calendar
Recent Comments
My LinksBlog Statistics
Syndicate
Powered byWho Visited? |
|||||||||||||||||||||||||||||||||||||||||||||||||
我在努力的成为高龄it 民工 ::D ::D