所以,假设我有一个这样的脚本。
log_files=(output_{console,stdout,stderr}.log)
do_stuff 2>"${log_files[2]}" 1>"${log_files[1]}"
虽然该函数应该将 stdout 重定向到"${log_files[1]}"
stderr "${log_files[2]}"
,但我也希望"${log_files[0]}"
同时将 stdout 和 stderr 重定向到。如何才能做到这一点?
答案1
这在 zsh 中会容易得多,multios
如果同一个 fd 上有多个重定向,shell 会执行一些内部魔法将输出发送到所有目的地,例如:
% do_stuff > stdout.log 2> stderr.log &> both.log
(请注意,由于处理重复输出的中间进程,输出到 stdout 和 stderr 之间的顺序可能会混淆。)
答案2
球座
回想一下echo "foo" | tee --append log.txt
问球座
将“foo”发送到文件和文件描述符 1。
这会将“foo”放入一对文件中:
echo "foo" | tee --append one.txt >> two.txt
因此,您可以重定向到一对子 shell,每个子 shell 将传入文本记录到一对文件中。
命名管道
如果您需要更大的灵活性,您也可以创建命名管道,然后对结果应用任意逻辑。
$ mkfifo /tmp/stdout
$ mkfifo /tmp/stderr
将文件描述符 1 和 2 发送给它们,就像您已经在做的那样。在另一个终端选项卡或后台守护程序中,运行tail -f
或其道德等效项以从每个终端检索文本行先进先出实时。使用正则表达式进行过滤,用时间戳进行修饰,做任何您喜欢的事情,然后将结果写入您想要的任意数量的接收器。
答案3
或者,要在没有命名管道的情况下执行此操作,您可以使用此问题的答案:https://stackoverflow.com/questions/16497317/piping-both-stdout-and-stderr-in-bash
将 stdout 和 stderr 分别通过管道传输到它们自己的 tee 副本,两者都附加到同一文件,并写入所需的各个文件。
然而,并非所有 tee 的实现都会安全地执行此操作,因此在某些情况下,您可能最终会在“both”文件中奇怪地散布 stdout 和 stderr 块。
据我所知,tee 没有办法强制进行安全的基于行的缓冲。