如何在使用管道使用“tee”时将stderr写入文件?

我有一个命令,它会将aaa.sh的输出打印到屏幕上,同时将stdout写入bbb.out ; 但是我也想写一个名为ccc.out的文件stderr。 有关如何修改下面的内容的任何建议?

./aaa.sh | tee ./bbb.out

更新:无论如何,stdout和stderr都应该被打印到屏幕上。


我假设你还想在终端上看到STDERR和STDOUT。 你可以去乔许·凯利的回答,但我觉得保持一个tail在输出日志文件非常hackish的和cludgy背景周围。 注意你需要保留一个exra FD,然后通过杀死它来进行清理,并且在技术上应该在trap '...' EXIT这样做trap '...' EXIT

有一个更好的方法来做到这一点,你已经发现它: tee

只是,不要仅仅将它用于stdout,而应该为stdout开发一个tee,为stderr开一个。 你将如何做到这一点? 进程替换和文件重定向:

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

让我们分解并解释:

> >(..)

>(...) (进程替换)创建一个FIFO并让tee监听它。 然后,它使用> (文件重定向)将command的STDOUT重定向到第一个tee正在侦听的FIFO。

第二件事情同样如此:

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

我们再次使用进程替换来创建一个从STDIN读取并将其转储到stderr.logtee进程。 tee在STDOUT上输出它的输入,但由于它的输入是我们的STDERR,我们希望再次将tee的STDOUT重定向到STDERR。 然后我们使用文件重定向将command的STDERR重定向到FIFO的输入( tee的STDIN)。

请参阅http://mywiki.wooledge.org/BashGuide/InputAndOutput

过程替换是你选择bash作为你的shell而不是sh (POSIX或Bourne)的奖励的真正可爱的东西之一。


sh ,你必须手动完成任务:

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

为什么不简单:

./aaa.sh 2>&1 | tee -a log

这只是将stderr重定向到stdout ,因此tee会同时回显登录和屏幕。 也许我错过了一些东西,因为其他一些解决方案似乎很复杂。

注意:由于bash版本4,您可以使用|&作为2>&1 |的缩写 :

./aaa.sh |& tee -a log

这可能对通过谷歌搜索此人有用。 简单地取消注释您想要尝试的示例。 当然,可以随意重命名输出文件。

#!/bin/bash

STATUSFILE=x.out
LOGFILE=x.log

### All output to screen
### Do nothing, this is the default


### All Output to one file, nothing to the screen
#exec > ${LOGFILE} 2>&1


### All output to one file and all output to the screen
#exec > >(tee ${LOGFILE}) 2>&1


### All output to one file, STDOUT to the screen
#exec > >(tee -a ${LOGFILE}) 2> >(tee -a ${LOGFILE} >/dev/null)


### All output to one file, STDERR to the screen
### Note you need both of these lines for this to work
#exec 3>&1
#exec > >(tee -a ${LOGFILE} >/dev/null) 2> >(tee -a ${LOGFILE} >&3)


### STDOUT to STATUSFILE, stderr to LOGFILE, nothing to the screen
#exec > ${STATUSFILE} 2>${LOGFILE}


### STDOUT to STATUSFILE, stderr to LOGFILE and all output to the screen
#exec > >(tee ${STATUSFILE}) 2> >(tee ${LOGFILE} >&2)


### STDOUT to STATUSFILE and screen, STDERR to LOGFILE
#exec > >(tee ${STATUSFILE}) 2>${LOGFILE}


### STDOUT to STATUSFILE, STDERR to LOGFILE and screen
#exec > ${STATUSFILE} 2> >(tee ${LOGFILE} >&2)


echo "This is a test"
ls -l sdgshgswogswghthb_this_file_will_not_exist_so_we_get_output_to_stderr_aronkjegralhfaff
ls -l ${0}
链接地址: http://www.djcxy.com/p/42693.html

上一篇: How do I write stderr to a file while using "tee" with a pipe?

下一篇: Apple rejection for black bar on top of ipad screen for an iPhone application