linux shell 屏幕显示stdout stderr的同时 分别重定向到文件

转载 2013年12月04日 22:40:50

I'm assuming you want to still see STDERR and STDOUT on the terminal. You could go for Josh Kelley's answer, but I find keeping a tail around in the background which outputs your log file very hackish and cludgy. Notice how you need to keep an exra FD and do cleanup afterward by killing it and technically should be doing that in a trap '...' EXIT.

There is a better way to do this, and you've already discovered it: tee.

Only, instead of just using it for your stdout, have a tee for stdout and one for stderr. How will you accomplish this? Process substitution and file redirection:

command > >(tee stdout.log) 2> >(tee stderr.log >&2)

Let's split it up and explain:

> >(..)

>(...) (process substitution) creates a FIFO and lets tee listen on it. Then, it uses > (file redirection) to redirect the STDOUT of command to the FIFO that your first tee is listening on.

Same thing for the second:

2> >(tee stderr.log >&2)

We use process substitution again to make a tee process that reads from STDIN and dumps it intostderr.logtee outputs its input back on STDOUT, but since its input is our STDERR, we want to redirect tee's STDOUT to our STDERR again. Then we use file redirection to redirect command's STDERR to the FIFO's input (tee's STDIN).

See http://mywiki.wooledge.org/BashGuide/InputAndOutput

Process substitution is one of those really lovely things you get as a bonus of choosing bash as your shell as opposed to sh (POSIX or Bourne).


In sh, you'd have to do things manually:

out="${TMPDIR:-/tmp}/out.$$" err="${TMPDIR:-/tmp}/err.$$"
mkfifo "$out" "$err"
trap 'rm "$out" "$err"' EXIT
tee stdout.log < "$out" &
tee stderr.log < "$err" >&2 &
command >"$out" 2>"$err"

6. Miscellaneous Operators

Aside from the standard I/O operators, bash also provides a few more advanced operators that make life on the shell that much nicer.

6.1. Process Substitution

A cousin of the pipe is the process substitution operator, which comes in two forms: <() and >(). It's a convenient way to use named pipes without having to create temporary files. Whenever you think you need a temporary file to do something, process substitution might be a better way to handle things.

What it does, is basically run the command inside the parentheses. With the <() operator, the command's output is put in a named pipe (or something similar) that's created by bash. The operator itself in your command is replaced by the filename of that file. After your whole command finishes, the file is cleaned up.

Here's how we can put that into action: Imagine a situation where you want to see the difference between the output of two commands. Ordinarily, you'd have to put the two outputs in two files and diff those:

$ head -n 1 .dictionary > file1
$ tail -n 1 .dictionary > file2
$ diff -y file1 file2
Aachen                                                        | zymurgy
$ rm file1 file2

Using the Process Substitution operator, we can do all that with a one-liner and no need for manual cleanup:

$ diff -y <(head -n 1 .dictionary) <(tail -n 1 .dictionary)
Aachen                                                        | zymurgy

The <(..) part is replaced by the temporary FIFO created by bash, so diff actually sees something like this:

$ diff -y /dev/fd/63 /dev/fd/62

Here we see how bash runs diff when we use process substitution. It runs our head and tail commands, redirecting their respective outputs to the "files"/dev/fd/63 and /dev/fd/62. Then it runs the diff command, passing those filenames where originally we had put the process substitution operators.

The actual implementation of the temporary files differs from system to system. In fact, you can see what the above would actually look like to diff on your box by putting an echo in front of our command:

$ echo diff -y <(head -n 1 .dictionary) <(tail -n 1 .dictionary)
diff -y /dev/fd/63 /dev/fd/62

The >(..) operator is much like the <(..) operator, but instead of redirecting the command's output to a file, we redirect the file to the command's input. It's used for cases where you're running a command that writes to a file, but you want it to write to another command instead:

$ tar -cf >(ssh host tar xf -) .


zz:http://stackoverflow.com/questions/692000/how-do-i-write-stderr-to-a-file-while-using-tee-with-a-pipe


相关文章推荐

echo输出到stderr

echo输出到stderr On the unix command line, each command can print to stdout (standard output) or s...

Shell 输入/输出重定向

概述大多数 UNIX 系统命令从你的终端接受输入并将所产生的输出发送回​​到您的终端。一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端。同样,一个命令通常将其输出写入到标准输出...

第4章 处理用户输入与显示数据------------(标准文件描述符、STDIN/STDERR/STDOUT、临时重定向、永久重定向exec)

4.4 显示数据 4.4.1 标准文件描述符          Linux系统将每个对象当作文件处理。这包括输入和输出过程。Linux使用文件描述符(file descriptor)标识每个文件对象。...

Linux下的shell编程(六)--函数,重定向,文件

一、Shell函数:Shell函数返回值、删除函数、在终端调用函数 函数可以让我们将一个复杂功能划分成若干模块,让程序结构更加清晰,代码重复利用率更高。像其他编程语言一样,Shell也支持函数。Sh...

Linux中的stdout和stderr

1,在linux中,标准输出和标准错误默认都是将信息输出到终端上,那么他们有什么区别呢?让我们来看个题目:问题:下面程序的输出是什么?(intel笔试2011)#include int main() ...
  • Q565220
  • Q565220
  • 2016年02月03日 17:03
  • 1309

linux下的stdin,stdout,stderr详解

stdout, stdin, stderr的中文名字分别是标准输出,标准输入和标准错误。   在Linux下,当一个用户进程被创建的时候,系统会自动为该进程创建三个数据 流,也就是题目中所提到的...

Linux 技巧:重定向 stderr 和 stdout 输出到 gdb 窗口

本文介绍了一个实用 gdb 调试技巧。 它结合实际例子,一步一步示意如何重定向 stderr 和 stdout 到 gdb窗口,使得查看应用程序的输出信息更为方便,从而提高调试者的工作效率。 ...

Linux 标准 输入 输出 重定向. printf 不输出到屏幕的解决办法

方法1: #include #include #include #include #include int main() { fflush(stdout); ...

给定A, B两个整数,不使用除法和取模运算,求A/B的商和余数

给定A, B两个整数,不使用除法和取模运算,求A/B的商和余数。 1.   最基本的算法是,从小到大遍历: for (i = 2 to A -1)          if (i * B > A)...

利用K-means聚类算法根据经纬度坐标对中国省市进行聚类

K-means聚类算法是一种非层次聚类算法,在最小误差的基础上将数据划分了特定的类,类间利用距离作为相似度指标,两个向量之间的距离越小,其相似度就越高。程序读取全国省市经纬度坐标,然后根据经纬度坐标进...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:linux shell 屏幕显示stdout stderr的同时 分别重定向到文件
举报原因:
原因补充:

(最多只允许输入30个字)