在bash中,调用foo将在stdout上显示该命令的任何输出。
调用foo > output会将该命令的任何输出重定向到指定的文件(在本例中为"output")。
有没有方法将输出重定向到一个文件,并在stdout上显示它?
- 如果有人在这里寻找错误输出到文件,请查看-unix.stackexchange.com/questions/132511/…
- 术语说明:当执行foo > output时,数据被写入stdout,stdout是名为output的文件。也就是说,写入文件就是写入stdout。您询问是否可以同时向stdout和终端写入。
您需要的命令名为tee:
例如,如果您只关心stdout:
如果要包括stderr,请执行以下操作:
1
| program [arguments...] 2>&1 | tee outfile |
2>&1将通道2(stderr/standard error)重定向到通道1(stdout/standard output),使两者都写为stdout。从tee命令开始,它也被定向到给定的输出文件。
此外,如果要附加到日志文件,请使用tee -a作为:
1
| program [arguments...] 2>&1 | tee -a outfile |
- 如果OP希望"所有输出"被重定向,还需要获取stderr:"ls-lr/2>&;1 tee output.file"
- 这个答案是错误的,下面的答案是正确的,不确定所有的赞成票是关于什么的。
- @埃文麦克唐纳的答案并不是错的,只是可能不够具体,也可能不够完整,这取决于你的要求。在某些情况下,您可能不希望stderr作为保存到文件的输出的一部分。当我5年前回答这个问题的时候,我假设那个组织只想要性传播疾病,因为他在帖子里提到了性传播疾病。
- 啊,对不起,我可能有点困惑。当我尝试的时候,我只是没有输出,也许所有的输出都会变成stderr。
- 使用tee上的-a参数将内容追加到output.file中,而不是覆盖:ls -lR / | tee -a output.file中。
- 我正在运行的是python main.py / | tee output.file,我的脚本认为/是命令的一个论点,并且正在发疯。有办法解决这个问题吗?
- 是否可以使答案相对独立?例如,可以解释命令的每个部分做什么,比如/等?
- ls -lR /过于混乱。如果你只使用像ls这样简单的东西就更清楚了。
- 我很好奇为什么我的编辑,删除了-lR /,因为"偏离了最初的意图"而被拒绝。也许审稿人没有真正读过这个问题?或者我误解了行动的意图?
- @Nealgokli我没有看到你的编辑,我在我的示例中添加了-lR /,以确定屏幕上确实会显示输出。一个简单的ls实际上可能不会输出任何东西,比如一个用户当前在一个空目录中,或者一个带有隐藏文件的目录中。它是Linux,因此我可以提供大量其他示例,这些示例肯定会提供输出。可能有点像od -t x2 /dev/urandom | tee outputfile.txt。
- 哦,说得对!我没想到。但是,难道-lR不是不必要的吗?也许是一个简单的ls -a?(因为至少有一个人似乎被/混淆了)。我不想承认,我一开始也有点困惑。)或者可能是从最初的问题中使用foo。我将尝试另一个编辑:)
- 如果之后使用$?,它将返回tee的状态代码,这可能不是您想要的。相反,您可以使用${PIPESTATUS[0]}。
- 对于一个工具命令,终端中有很多警告消息和错误,但我无法使用>或tee进入文件。它只捕获第一行
- @您可能需要包括stderr。即... 2>&1 | tee ...。
1
| $ program [arguments...] 2>&1 | tee outfile |
2>&1转储stderr和stdout流。tee outfile获取它得到的流并将其写入屏幕和文件"outfile"。
这可能是大多数人正在寻找的。可能的情况是,某些程序或脚本工作很长时间,并产生大量输出。用户希望定期检查它的进度,但也希望将输出写入文件。
问题(尤其是在混合stdout和stderr流时)在于依赖程序所刷新的流。例如,如果对stdout的所有写入都没有刷新,但对stderr的所有写入都被刷新,那么它们将以输出文件和屏幕上的时间顺序结束。
如果程序每隔几分钟只输出1或2行来报告进度,那也很糟糕。在这种情况下,如果输出没有被程序刷新,用户甚至在几个小时内都不会在屏幕上看到任何输出,因为没有一个输出会被推过管道几个小时。
更新:expect包的一部分,程序unbuffer将解决缓冲问题。这将导致stdout和stderr在合并并重定向到tee时立即写入屏幕和文件并保持同步。例如。:
1
| $ unbuffer program [arguments...] 2>&1 | tee outfile |
- 找到解决方案:链接
- 有人知道OSX的"无缓冲"吗?
- 如果您不能使用unbuffer,gnu coreutils包括一个名为stdbuff的工具,它可以用来防止输出缓冲,如$ stdbuf -o 0 program [arguments...] 2>&1 | tee outfile。
- 这,这正是我一直在寻找的!我在用一个我没有写的程序tee,在stdout被刷新之前我必须等待一分钟。Unbuffer解决了这个问题!值得注意的是@peter的stdbuf解决方案不起作用,在输出出现在我的文件中之前,我仍然经历了很长的等待时间。
- 如果您使用的是OSX,那么在大多数情况下使用Unbuffer会稍微容易一些,但如果您想将信号传递给正在运行的命令,则不是这样。我的评论更针对的是Linux上的用户,默认情况下,coreutils最有可能安装在Linux上。@伊桑,如果你对stdbuf语法感到困惑,请看这个答案:stackoverflow.com/a/25548995/942781
- @彼得,我在运行linux mint。我只是用你在回答中给出的论点来尝试stdbuf。这很好地说明了信号的复杂性,幸运的是我的用例相当简单。感谢您的精心设计!
- 注意,python有一个内置选项-u,可以取消缓冲输出。
另一个对我有用的方法是,
1
| <command> |& tee <outputFile> |
如GNU BASH手册所示
例子:
If ‘|&’ is used, command1’s standard error, in addition to its standard output, is connected to command2’s standard input through the pipe; it is shorthand for 2>&1 |. This implicit redirection of the standard error to the standard output is performed after any redirections specified by the command.
有关详细信息,请参阅重定向
- 如果之后使用$?,它将返回tee的状态代码,这可能不是您想要的。相反,您可以使用${PIPESTATUS[0]}。
- 这个方法丢弃彩色控制台输出,有什么想法吗?
- 尝试:unbuffer ls-l--color=auto tee files.txt
您可以主要使用zoredache解决方案,但如果不想覆盖输出文件,则应使用-a选项编写tee,如下所示:
1
| ls -lR / | tee -a output.file |
要添加的内容…
包Unbuffer在Fedora和Redhat Unix版本下的某些包存在支持问题。
抛开烦恼
跟随者为我工作
1
| bash myscript.sh 2>&1 | tee output.log |
Thank you ScDF & matthew your inputs saved me lot of time..
使用tail -f output应该有效。
奖金答案,因为这个用例把我带到这里:
如果您需要像其他用户一样执行此操作
1
| echo"some output" | sudo -u some_user tee /some/path/some_file |
请注意,echo将以"some_user"的身份发生,而文件写入将以"some_user"的身份发生,如果要以"some_user"的身份运行echo并使用>>"some_file"重定向输出,则不起作用,因为文件重定向将以您的身份发生。
提示:tee还支持带-a标志的append,如果您需要将文件中的一行替换为另一个用户,则可以作为所需用户执行sed。
< command > |& tee filename这将创建一个命令状态为内容的文件"文件名",如果文件已经存在,它将删除已存在的内容并写入命令状态。
< command > | tee >> filename这将向文件附加状态,但不会在标准输出(屏幕)上打印命令状态。
我想通过在屏幕上使用"echo"来打印一些东西,并将这些回显的数据附加到一个文件中。
1
| echo"hi there, Have to print this on screen and append to a file" |
通过在脚本开头使用类似的方法,可以对整个脚本执行此操作:
1 2 3 4 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 |
这会将stderr和stdout输出重定向到名为mylogfile的文件,并让所有内容同时转到stdout。
它使用了一些愚蠢的技巧:
- 在没有命令的情况下使用exec来设置重定向,
- 使用tee复制输出,
- 用所需的重定向重新启动脚本,
- 使用特殊的第一个参数(由$'string'特殊bash符号指定的简单NUL字符)来指定重新启动脚本(您的原始工作不能使用等效的参数)。
- 使用pipefail选项重新启动脚本时,请尝试保留原始退出状态。
丑陋但在某些情况下对我有用。
T恤很适合这个,但这也可以
1
| ls -lr / > output | cat output |
- 如果输出已经不存在,并且它不做您想要的事情,那么这就是一个错误。如果它确实存在,那么总的来说,这是无稽之谈。也许你的意思是""而不是""?
- 即使使用了;,在慢命令期间输出也会延迟很多。