将输出同时发送到标准输出和标准错误流

21

我有一个非常简单的初学者问题: 如何在shell脚本中将echo输出到标准输出和标准错误输出? 我知道可以将echo输出到标准错误输出,例如echo "foo" 1>&2,但我需要同时输出到两个地方。 我尝试了一些谷歌搜索但没有起作用。


可能是将bash的stdout/stderr重定向到两个位置?的重复问题。虽然不完全相同,但如果您只需将进程设置为cat >&2,答案仍然有效。 - Nemo
4个回答

29

这应该可以解决问题

 echo "foo" | tee /dev/stderr 

3
假设你的系统支持/dev/stderr。我认为大多数或所有现代类Unix系统都支持,但如果你担心古老的系统:line="foo"; echo "$line" ; echo "$line" 1>&2。很容易将其包装在别名或函数中。 - Keith Thompson
2
注意:在1>&2中不需要1echo $line >&2可以达到同样的效果。 - TWiStErRob
1
FYI - busybox 的 init 程序似乎不支持 /dev/stderr - ACK_stoverflow

17
echo foo | tee >(cat >&2)

即使不支持stderr,这也可以正常工作。

注意:如果您已经su到另一个帐户并且该帐户具有对tty的写权限,则Soren的答案将无法正常工作;但我的答案可以。


2
需要 bash 吗?简单的 Bourne shell 输出 sh: Syntax error: "(" unexpected (expecting word) - zezollo

0

另一个解决方案,可能仅适用于Linux内核(及其/proc/文件系统),但不需要bash:

echo foo | tee /proc/$$/fd/2

在这里,$$ 包含正在运行的进程的 PID,而 /proc/some_pid/fd/2 将指向进程 some_pid 的文件描述符号 2。我们只是指示 tee 直接写入标准错误输出(编号为 2)的文件描述符号,该标准错误输出属于由其 PID $$ 标识的 shell 进程。

Tee 还输出到其标准输出,该输出未被重定向并最终出现在 stdout (fd 1) 上。


0

我也同意对问题的评论:正如链接的答案所示,可以创建一个指向我们的stderr文件描述符的FIFO,然后使用tee将其写入:

mkfifo /tmp/temp_fifo_file # this named fifo will appear in the /tmp directory
(cat /tmp/temp_fifo_file >&2 &) # Background `cat` process: read the fifo and echo to stderr
echo foo | tee /tmp/temp_fifo_file
rm /tmp/temp_fifo_file # cleanup

关于上面的两点说明:当收到EOF时,cat将关闭fifo并退出,因此它只能工作一次。我使用括号(子shell)来隐藏作业控制消息,但是它也可以不用。

为了避免关闭管道,它可以被打开为读写(确保阅读链接的警告,可能最好将exec放在与cat相同的子shell中,但这使得关闭文件描述符更加困难):

mkfifo /tmp/temp_fifo_file # this named fifo will appear in the /tmp directory
exec 3<>/tmp/temp_fifo_file # Open fifo as fd 3
(cat 0<&3 1>&2 & ) # stays in the background, cat reads fd 3 and outputs to stderr
echo foo | tee /tmp/temp_fifo_file
# Cleanup:
exec 3<&- # Close fd 3, this will terminate background job
rm /tmp/temp_fifo_file # remove fifo

注意:在 (cat 0<&3 1>&2 & ) 中,0和1可以省略,因为它们分别代表默认的标准输入和输出。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接