如何将输出重定向到文件和标准输出
技术背景
在日常使用命令行时,我们经常会遇到这样的情况:一些程序或脚本运行时间长且产生大量输出,我们既希望能实时查看输出以了解进度,又希望将输出保存到文件中以便后续分析。此时,就需要将输出同时重定向到文件和标准输出(stdout)。
实现步骤
仅处理标准输出
若只关注标准输出,可以使用 tee
命令,它可以将输入复制到标准输出和指定文件。例如:
上述命令会将 ls -a
的输出同时显示在屏幕上并保存到 output.file
中。
包含标准错误输出
如果要同时包含标准错误输出(stderr),可以使用 2>&1
将标准错误输出重定向到标准输出,再使用 tee
命令:
1
| program [arguments...] 2>&1 | tee outfile
|
追加到日志文件
若要将输出追加到已有的日志文件,可使用 tee -a
:
1
| program [arguments...] 2>&1 | tee -a outfile
|
核心代码
基本使用
包含标准错误输出
1
| program [arguments...] 2>&1 | tee outfile
|
追加到日志文件
1
| program [arguments...] 2>&1 | tee -a outfile
|
使用 unbuffer
解决缓冲区问题
1
| unbuffer program [arguments...] 2>&1 | tee outfile
|
使用 |&
简化命令
1
| <command> |& tee <outputFile>
|
以其他用户身份执行
1
| echo "some output" | sudo -u some_user tee -a /some/path/some_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 $? ; }
|
最佳实践
- 缓冲区问题:当程序输出不及时刷新缓冲区时,可能导致输出顺序混乱或长时间无输出显示。可以使用
unbuffer
命令(属于 expect
包)解决缓冲区问题:
1
| unbuffer program [arguments...] 2>&1 | tee outfile
|
- 简化命令:使用
|&
可以简化将标准错误输出和标准输出同时重定向的命令:
常见问题
输出顺序混乱
当混合标准输出和标准错误输出流时,由于程序对输出流刷新的依赖,可能导致输出在文件和屏幕上的顺序不符合时间顺序。解决方法是使用 unbuffer
命令。
unbuffer
支持问题
unbuffer
包在某些 Fedora 和 Red Hat Unix 发行版下可能存在支持问题。可以尝试使用其他方法,如在脚本中使用 2>&1
和 tee
:
1
| bash myscript.sh 2>&1 | tee output.log
|
不使用 tee
的方法
如果不想使用 tee
,可以使用以下方法将输出同时显示在屏幕和保存到文件:
1
| echo "some content" > /dev/tty > log_file.txt
|
这里 /dev/tty
是终端的字符设备。