在bash中,调用foo
会在stdout上显示该命令的任何输出。
调用foo > output
会将该命令的任何输出重定向到指定的文件(在本例中为'output')。
有没有办法将输出重定向到文件和让它显示在stdout上?
答案 0 :(得分:1105)
您想要的命令名为 tee
:
foo | tee output.file
例如,如果你只关心stdout:
ls -a | tee output.file
如果你想包括stderr,请执行:
program [arguments...] 2>&1 | tee outfile
2>&1
将通道2(stderr /标准错误)重定向到通道1(标准输出/标准输出),这样两者都被写为标准输出。它还指向tee
命令的给定输出文件。
此外,如果您想追加到日志文件,请使用tee -a
:
program [arguments...] 2>&1 | tee -a outfile
答案 1 :(得分:468)
$ program [arguments...] 2>&1 | tee outfile
2>&1
转储stderr和stdout流。
tee outfile
获取它获取的流并将其写入屏幕和文件“outfile”。
这可能是大多数人都在寻找的。可能的情况是某些程序或脚本长时间努力并产生大量输出。用户希望定期检查进度,但也希望将输出写入文件。
问题(特别是在混合stdout和stderr流时)是依赖于程序刷新的流。例如,如果对stdout的所有写入都是而不是已刷新,但是对stderr 的所有写入都被刷新,那么它们将在输出中按时间顺序排列文件和屏幕上。
如果程序每隔几分钟只输出1或2行来报告进度,那也很糟糕。在这种情况下,如果程序没有刷新输出,用户甚至不会在屏幕上看到任何数小时的输出,因为它们都不会在数小时内通过管道。
更新:程序unbuffer
是expect
包的一部分,将解决缓冲问题。这将导致stdout和stderr立即写入屏幕和文件,并在组合并重定向到tee
时保持同步。 E.g:
$ unbuffer program [arguments...] 2>&1 | tee outfile
答案 2 :(得分:110)
另一种对我有用的方法是,
<command> |& tee <outputFile>
所示
示例:
ls |& tee files.txt
如果使用'|&amp;',command1的标准错误,除标准输出外,还通过管道连接到command2的标准输入;它是 2&gt;&amp; 1 |的简写。标准错误到标准输出的隐式重定向是在命令指定的任何重定向之后执行的。
有关详细信息,请参阅redirection
答案 3 :(得分:16)
答案 4 :(得分:11)
Something to add ...
The package unbuffer has support issues with some packages under fedora and redhat unix releases.
Setting aside the troubles
Following worked for me
bash myscript.sh 2>&1 | tee output.log
答案 5 :(得分:6)
使用tail -f output
应该有效。
答案 6 :(得分:3)
奖励回答,因为这个用例让我来到这里:
如果您需要像其他用户一样
echo "some output" | sudo -u some_user tee /some/path/some_file
请注意,回声将发生在您身上,文件写入将发生为“some_user”,如果您将echo作为“some_user”运行并将输出重定向为&gt;那么 NOT 工作的是什么;&GT; “some_file”因为文件重定向将像你一样发生。
提示:tee还支持附加-a标志,如果你需要将文件中的一行替换为另一个用户,你可以将sed作为所需用户执行。
答案 7 :(得分:1)
< command > |& tee filename
#这将创建一个文件&#34; filename&#34;将命令状态作为内容,如果文件已存在,则会删除现有内容并写入命令状态。
< command > | tee >> filename
#这会将状态追加到文件中,但它不会在standard_output(屏幕)上打印命令状态。
我想通过使用&#34; echo&#34;来打印一些东西。在屏幕上并将回显的数据附加到文件
echo "hi there, Have to print this on screen and append to a file"
答案 8 :(得分:0)
您可以通过在脚本的开头使用类似的方法来对整个脚本执行此操作:
#!/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'
字符)来指定脚本已重新启动(原始工作不得使用等效参数),< / li>
pipefail
选项重新启动脚本时保留原始退出状态。丑陋,但在某些情况下对我有用。
答案 9 :(得分:0)
另一个方便的选择是使用screen命令运行主程序并将stderr和stdout定向到文件,然后使用tail -f查看正在写入的文件。
如果您不想使用屏幕,也可以打开另一个会话。
答案 10 :(得分:-10)
ls -lr / > output | cat output