如何将输出重定向到文件和标准输出

SCd*_*CdF 898 linux io bash file-io stdout

在bash中,调用foo将在stdout上显示该命令的任何输出.

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

有没有办法将输出重定向到文件并将其显示在stdout上?

Zor*_*che 1234

您想要的命令命名为tee:

foo | tee output.file
Run Code Online (Sandbox Code Playgroud)

例如,如果你只关心stdout:

ls -a | tee output.file
Run Code Online (Sandbox Code Playgroud)

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

program [arguments...] 2>&1 | tee outfile
Run Code Online (Sandbox Code Playgroud)

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

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

program [arguments...] 2>&1 | tee -a outfile
Run Code Online (Sandbox Code Playgroud)

  • 如果OP要重定向"all output",你还需要抓住stderr:"ls -lR/2>&1 | tee output.file" (164认同)
  • @evanmcdonnal答案没有错,根据您的要求可能不够具体或完整.当然,您可能不希望将stderr作为输出的一部分保存到文件中.当我5年前回答这个问题时,我认为OP只想要stdout,因为他在帖子的主题中提到了stdout. (43认同)
  • 在`tee`上使用`-a`参数将内容附加到`output.file`,而不是覆盖它:`ls -lR/| tee -a output.file` (34认同)
  • 如果你之后使用`$?`,它将返回`tee`的状态代码,这可能不是你想要的.相反,你可以使用`$ {PIPESTATUS [0]}`. (14认同)
  • 对不起,我可能有点困惑.当我尝试它时,我没有输出,也许它都是stderr. (3认同)
  • 旁白:我想知道为什么该命令被称为“tee”,并意识到 T 形可能代表信息流。想象一下信息(命令的输出)从左边进来;它既“向下”定向到输出文件,也允许直接继续到“stdout”... (2认同)

Mat*_*ert 485

$ program [arguments...] 2>&1 | tee outfile
Run Code Online (Sandbox Code Playgroud)

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

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

问题(特别是在混合stdout和stderr流时)是依赖于程序刷新的流.如果,例如,所有的写入stdout都没有刷新,但所有写至标准错误刷新,那么他们最终会出在输出文件中按时间顺序排列,并在屏幕上.

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

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

$ unbuffer program [arguments...] 2>&1 | tee outfile
Run Code Online (Sandbox Code Playgroud)

  • 有人知道osx的'unbuffer'吗? (6认同)
  • 如果您不能使用unbuffer,GNU coreutils包含一个名为[stdbuff]的工具(http://www.gnu.org/software/coreutils/manual/html_node/stdbuf-invocation.html),可用于防止输出缓冲像这样`$ stdbuf -o 0 program [arguments ...] 2>&1 | tee outfile` (6认同)
  • 如果您使用的是 OS X,在大多数情况下使用 unbuffer 会稍微容易一些,但如果您想将信号传递给正在运行的命令则不然。我的评论更多针对 Linux 上的用户,其中 coreutils 很可能是默认安装的。@Ethan,如果您对 stdbuf 语法感到困惑,请参阅此答案:http://stackoverflow.com/a/25548995/942781 (2认同)
  • 注意,`python`有一个内置选项`-u`,用于取消输出缓冲。 (2认同)
  • 用于训练 ML 模型的绝对救星,我想在没有额外代码的情况下进行日志记录,但还要查看运行所需的数小时/天的输出,谢谢! (2认同)

tse*_*thy 118

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

<command> |& tee  <outputFile>
Run Code Online (Sandbox Code Playgroud)

gnu bash手册中所示

例:

ls |& tee files.txt
Run Code Online (Sandbox Code Playgroud)

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

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

  • 如果你之后使用`$?`,它将返回`tee`的状态代码,这可能不是你想要的.相反,你可以使用`$ {PIPESTATUS [0]}`. (10认同)
  • 这种方法丢弃彩色控制台输出,有什么想法吗? (2认同)

Jac*_*bec 17

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

my_java_process_run_script.sh |& tee logfile
Run Code Online (Sandbox Code Playgroud)

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

  • 也许要提到“|&amp;”简写将 stdout 和 stderr 重定向到管道中(相当于“2&gt;&amp;1 | ...”)。可能使用“tee -a”附加到现有文件。 (6认同)

O.B*_*adr 16

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

ls -lR / | tee -a output.file
Run Code Online (Sandbox Code Playgroud)


nit*_*708 11

要添加的东西......

软件包unbuffer在fedora和redhat unix版本下的某些软件包中存在支持问题.

抛开麻烦

以下为我工作

bash myscript.sh 2>&1 | tee output.log
Run Code Online (Sandbox Code Playgroud)

谢谢ScDF&matthew你的输入节省了我很多时间..


Chu*_*ips 6

使用tail -f output应该工作.


jor*_*fus 6

自从这个用例把我带到这里以来,额外的答案是:

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

echo "some output" | sudo -u some_user tee -a /some/path/some_file
Run Code Online (Sandbox Code Playgroud)

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

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


Bru*_*ILS 5

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

#!/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
Run Code Online (Sandbox Code Playgroud)

这两种重定向标准错误和标准输出输出到文件称为mylogfile 并且让一切都到stdout在同一时间

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

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

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