你想要调试一个比较长的管道化 I/O
序列,例如:
cat my* | tr 'a-z' 'A-Z' | uniq | awk -f transform.awk | wc
在不中断管道的情况下,该如何查看 uniq 和 awk 之间发生了什么?
解决方案
解决方案是使用水管工在维修管线时会用到的 T 形接头。对于 bash 来说,这意味着用 tee 命令将输出分成两个一模一样的流,一个写入文件,另一个写入标准输出,以便继续沿着管道发送数据。
对于上述示例,我们在 uniq 和 awk 之间插入 tee 命令:
... uniq | tee /tmp/x.x | awk -f transform.awk ...
讨论
tee 命令将输出写入其参数所指定的文件,同时还将相同的输出写入标准输出。在上述示例中,它将输出同时发送到 /tmp/x.x
和 awk,后者通过管道与 tee 的输出连接在一起。
不用关心示例中的这条命令的各个部分都是做什么的,我们只是演示 tee 命令在命令序列中的用法。
降低点儿难度,来看一个更简单的命令行。假设你想要将某个长期运行的命令的输出保存起来,以备随后参考,同时还想在屏幕上看到这些输出。思考下面的命令:
find / -name '*.c' -print | less
该命令会查找出大量的 C 程序源代码文件,可能需要好几屏的输出。使用 more 或 less 可以一次只查看部分输出,但命令结束后就无法回看之前的输出,除非再次运行命令。当然,你可以将输出保存到文件:
find / -name '*.c' -print > /tmp/all.my.sources
但这样的话,只有等到命令结束后才能看到文件内容。(好了,我们知道还有 tail -f
,但现在说这个就跑题了。)tee 命令可以用来代替重定向标准输出的做法:
find / -name '*.c' -print | tee /tmp/all.my.sources
在这个例子中,因为 tee 的输出并未重定向到别处,因此会显示在屏幕上。但是输出的副本也会发送给指定的文件(如 cat /tmp/all.my.sources
),以备后用。
还要注意,在这几个例子中,我们压根没有重定向过标准错误。这意味着错误(如来自 find 命令)会显示在屏幕上,但不会出现在 tee 指定的文件中。我们可以在 find 命令中加入 2>&1
:
find / -name '*.c' -print 2>&1 | tee /tmp/all.my.sources
这样就可以将错误输出一并存入 tee 指定的文件。错误输出与普通输出之间未必泾渭分明,但的确能被捕获到。
酷客网相关文章:
评论前必须登录!
注册