1307

在 bash 中,调用foo会在标准输出上显示该命令的任何输出。

调用foo > output会将来自该命令的任何输出重定向到指定的文件(在本例中为“输出”)。

有没有办法将输出重定向到文件显示在标准输出上?

4

11 回答 11

1864

您想要的命令名为tee

foo | tee output.file

例如,如果您只关心标准输出:

ls -a | tee output.file

如果要包含 stderr,请执行以下操作:

program [arguments...] 2>&1 | tee outfile

2>&1将通道 2(stderr/标准错误)重定向到通道 1(stdout/标准输出),这样两者都写为 stdout。从命令开始,它也被定向到给定的输出文件tee

此外,如果要附加到日志文件,请使用tee -a

program [arguments...] 2>&1 | tee -a outfile
于 2009-01-07T01:48:08.943 回答
542
$ program [arguments...] 2>&1 | tee outfile

2>&1转储 stderr 和 stdout 流。 tee outfile获取它获取的流并将其写入屏幕和文件“outfile”。

这可能是大多数人正在寻找的。可能的情况是某些程序或脚本长时间工作并产生大量输出。用户希望定期检查进度,但也希望将输出写入文件。

问题(尤其是在混合 stdout 和 stderr 流时)是依赖于程序刷新的流。例如,如果对 stdout 的所有写入都没有刷新,但对 stderr 的所有写入都被刷新,那么它们最终会在输出文件和屏幕上不按时间顺序排列。

如果程序每隔几分钟只输出 1 或 2 行来报告进度,这也很糟糕。在这种情况下,如果程序没有刷新输出,用户甚至在几个小时内都不会在屏幕上看到任何输出,因为在几个小时内它都不会通过管道推送。

更新:程序unbufferexpect包的一部分,将解决缓冲问题。这将导致 stdout 和 stderr 立即写入屏幕和文件,并在合并和重定向到tee. 例如:

$ unbuffer program [arguments...] 2>&1 | tee outfile
于 2011-08-28T05:38:20.797 回答
152

另一种对我有用的方法是,

<command> |& tee  <outputFile>

gnu bash手册中所示

例子:

ls |& tee files.txt

如果使用'|&',command1的标准错误,除了它的标准输出,通过管道连接到command2的标准输入;它是2>&1 | 的简写。标准错误到标准输出的这种隐式重定向是在命令指定的任何重定向之后执行的。

有关更多信息,请参阅重定向

于 2015-03-20T10:03:47.283 回答
23

您可以主要使用Zoredache 解决方案,但如果您不想覆盖输出文件,您应该使用 -a 选项编写 tee,如下所示:

ls -lR / | tee -a output.file
于 2014-08-15T00:18:41.663 回答
18

有什么要补充的...

软件包 unbuffer 对 fedora 和 redhat unix 版本下的某些软件包有支持问题。

抛开烦恼

以下为我工作

bash myscript.sh 2>&1 | tee output.log

谢谢ScDF马修,您的意见为我节省了很多时间。

于 2015-06-26T10:10:45.980 回答
9

使用tail -f output应该工作。

于 2009-01-07T01:50:22.870 回答
6

您可以通过在脚本开头使用类似的内容来为整个脚本执行此操作:

#!/usr/bin/env bash

test x$1 = x$'\x00' && shift || { set -o pipefail ; ( exec 2>&1 ; $0 $'\x00' "$@" ) | tee mylogfile ; exit $? ; }

# do whaetever you want

这会将 stderr 和 stdout 输出重定向到调用的文件mylogfile ,并让所有内容同时进入 stdout 。

它使用了一些愚蠢的技巧:

  • 不使用exec命令设置重定向,
  • 用于tee复制输出,
  • 使用想要的重定向重新启动脚本,
  • 使用特殊的第一个参数(NUL由特殊 bash 表示法指定的简单字符$'string')来指定脚本重新启动(您的原始作品可能不使用等效参数),
  • 尝试使用该pipefail选项重新启动脚本时保留原始退出状态。

丑陋但在某些情况下对我有用。

于 2019-05-03T10:47:24.270 回答
4

奖励答案,因为这个用例把我带到了这里:

如果您需要以其他用户的身份执行此操作

echo "some output" | sudo -u some_user tee /some/path/some_file

请注意,回显将在您发生时发生,并且文件写入将以“some_user”的身份发生,如果您以“some_user”身份运行回显并使用>>“some_file”重定向输出,则将不起作用,因为文件重定向将发生和你一样。

提示: tee 还支持附加 -a 标志,如果您需要将文件中的一行替换为另一个用户,您可以作为所需用户执行 sed。

于 2015-10-22T17:55:42.220 回答
3

< command > |& tee filename# 这将创建一个以命令状态为内容的文件“文件名”,如果文件已经存在,它将删除现有内容并写入命令状态。

< command > | tee >> filename# 这会将状态附加到文件中,但不会在标准输出(屏幕)上打印命令状态。

我想通过在屏幕上使用“回显”来打印一些东西,并将回显的数据附加到文件中

echo "hi there, Have to print this on screen and append to a file" 
于 2018-02-01T16:25:04.510 回答
2

就我而言,我有带有输出日志的 Java 进程。显示输出日志并将它们重定向到文件(此处命名为 logfile)的最简单解决方案是:

my_java_process_run_script.sh |& tee logfile

结果是 Java 进程运行,输出日志显示并将它们放入名为 logfile 的文件中

于 2021-11-16T20:20:41.233 回答
-16

tee 非常适合这个,但这也可以完成工作

ls -lr / > output | cat output
于 2009-01-07T02:47:44.750 回答