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

How to redirect output to a file and stdout

提问人:SCdF 提问时间:1/7/2009 最后编辑:MikeSCdF 更新时间:9/29/2023 访问量:1056411

问:

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

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

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

Linux Bash 文件-IO IO 标准输出

评论

6赞 Murphy 10/19/2017
如果有人只是在这里寻找将错误输出捕获到文件,请看一下 - unix.stackexchange.com/questions/132511/...
9赞 William Pursell 5/3/2019
关于术语的说明:执行时,数据写入 stdout,stdout 名为 的文件。也就是说,写入文件就是写入 stdout。您正在询问是否可以同时写入 stdout 和终端。foo > outputoutput
4赞 Don Hatch 12/26/2019
@WilliamPursell 我不确定你的澄清是否能改善事情:-)怎么样:OP 询问是否可以将被调用程序的 stdout 定向到文件和调用程序的 stdout(后者是被调用程序如果不做任何特殊操作将继承的 stdout;即终端,如果调用程序是交互式 bash 会话)。也许他们也想以类似的方式指导被调用程序的 stderr(“该命令的任何输出”可以合理地解释为包括 stderr)。
0赞 EsmaeelE 12/11/2022
如果我们有多个想要通过管道输出的命令,请使用 .例如( )(echo hello; echo world) | tee output.txt

答:

2206赞 Zoredache 1/7/2009 #1

所需的命令名为 tee

foo | tee output.file

例如,如果您只关心 stdout:

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

评论

193赞 James Brady 1/13/2009
如果 OP 想要重定向“所有输出”,您还需要获取 stderr: “ls -lR / 2>&1 |tee output.文件”
49赞 Zoredache 10/1/2014
@evanmcdonnal 答案没有错,只是可能不够具体,或者根据您的要求完成。当然,在某些情况下,您可能不希望将 stderr 作为输出的一部分保存到文件中。当我在 5 年前回答这个问题时,我以为 OP 只想要 stdout,因为他在帖子的主题中提到了 stdout。
3赞 evanmcdonnal 10/2/2014
啊,对不起,我可能有点困惑。当我尝试它时,我只是没有得到任何输出,也许这一切都会变得很糟糕。
48赞 kazy 9/1/2015
使用 argument on 将内容附加到 ,而不是覆盖它:-ateeoutput.filels -lR / | tee -a output.file
25赞 LaGoutte 3/3/2017
如果你在之后使用,它将返回 的状态代码,这可能不是你想要的。相反,您可以使用 .$?tee${PIPESTATUS[0]}
10赞 Chuck Phillips 1/7/2009 #2

使用应该有效。tail -f output

-18赞 kal 1/7/2009 #3

T恤非常适合此,但这也可以完成这项工作

ls -lr / > output | cat output

评论

11赞 Robert Gamble 1/7/2009
如果输出不存在,那就是一个错误,如果它存在,它不会做你想要的,总的来说它是荒谬的。也许你的意思是“;”而不是“|”?
8赞 Brad Koch 4/18/2013
即使使用了 ,在慢速命令期间,输出也会有很大的延迟。;
570赞 Matthew Alpert 8/28/2011 #4
$ program [arguments...] 2>&1 | tee outfile

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

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

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

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

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

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

评论

8赞 John Mee 5/22/2012
有人知道 osx 的“unbuffer”吗?
9赞 Peter 7/2/2015
如果你不能使用 unbuffer,GNU coreutils 包含一个名为 stdbuff 的工具,它可以用来防止输出缓冲$ stdbuf -o 0 program [arguments...] 2>&1 | tee outfile
2赞 Peter 2/16/2016
如果您使用的是 OS X,则在大多数情况下使用 unbuffer 会稍微容易一些,但如果您想将信号传递给正在运行的命令,则不会。我的评论更针对的是 Linux 上的用户,其中 coreutils 很可能是默认安装的。@Ethan,如果您对 stdbuf 语法感到困惑,请参阅以下答案: stackoverflow.com/a/25548995/942781
15赞 fabian789 4/18/2016
请注意,它有一个内置选项,可以取消缓冲输出。python-u
5赞 rococo 5/29/2019
训练 ML 模型的绝对救星,我想在没有额外代码的情况下进行记录,但也可以看到运行所需数小时/数天的输出,谢谢!
25赞 O.Badr 8/15/2014 #5

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

ls -lR / | tee -a output.file
176赞 tsenapathy 3/20/2015 #6

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

<command> |& tee  <outputFile>

GNU Bash 手册所示

例:

ls |& tee files.txt

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

有关详细信息,请参阅重定向

评论

13赞 LaGoutte 3/3/2017
如果你在之后使用,它将返回 的状态代码,这可能不是你想要的。相反,您可以使用 .$?tee${PIPESTATUS[0]}
3赞 shakram02 6/22/2017
此方法丢弃了彩色控制台输出,有什么想法吗?
1赞 Luciano Andress Martini 8/3/2018
尝试:unbuffer ls -l --color=auto |TEE文件:.txt
0赞 Maf 9/27/2023
这不和Zoredache的答案是一回事吗?
18赞 nitinr708 6/26/2015 #7

要补充的东西......

软件包 unbuffer 对 fedora 和 redhat unix 发行版下的某些软件包存在支持问题。

抛开烦恼

以下对我有用

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

谢谢ScDFmatthew,你的输入为我节省了很多时间。

评论

1赞 Maf 9/27/2023
这似乎是重复的
4赞 jorfus 10/23/2015 #8

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

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

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

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

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

评论

0赞 Maf 9/27/2023
这个答案似乎是重复的,为什么你需要sudo?
0赞 jorfus 9/29/2023
想象一下,您正在向配置文件添加一行。配置文件归 root 所有。如果你'sudo echo “data” > /etc/config.cfg',它将失败。这个技巧允许你回答问题(如何将数据重定向到控制台和文件)并作为奖励重定向到root(或任何其他用户)拥有的文件
1赞 kiran sai 2/2/2018 #9

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

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

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

echo "hi there, Have to print this on screen and append to a file" 

评论

0赞 Maf 9/27/2023
这是另一个问题吗?
6赞 Bruno BEAUFILS 5/3/2019 #10

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

#!/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 输出重定向到调用的文件,让所有内容同时转到 stdout。mylogfile

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

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

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

15赞 Jackkobec 11/17/2021 #11

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

my_java_process_run_script.sh |& tee logfile

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

评论

5赞 tripleee 8/16/2022
也许可以提到速记将 stdout 和 stderr 重定向到管道中(相当于 )。可能用于追加到现有文件。|&2>&1 | ...tee -a