如何在Bash脚本内捕获所有输出到文件并保留终端打印
在Bash脚本内部捕获所有输出到文件并同时终端打印
嘿,这个需求其实挺容易实现的,不用在外部调用时加tee,咱们直接在脚本内部用Bash的进程替换和exec命令就能搞定。下面给你两种实用的方案:
方案一:把标准输出和错误输出合并到同一个日志文件
这种方式适合你想把所有输出(包括git pull的输出和脚本自己的提示)都存在同一个文件里,同时终端正常显示:
#!/bin/bash # 先定义日志文件的路径,你可以改成自己想要的名字 LOG_FILE="script_run.log" # 关键一步:用exec把stdout和stderr都重定向到tee进程 # tee会同时把内容输出到终端和追加到日志文件 exec > >(tee -a "$LOG_FILE") 2>&1 # 接下来的所有命令输出都会被自动捕获啦 git pull origin main echo "Operation took XX minutes" # 其他命令...
简单解释:
> >(tee -a "$LOG_FILE"):把脚本的标准输出(stdout)重定向到tee的进程替换里,tee负责把内容同时打印到终端和追加到日志文件(-a是追加模式,避免每次运行覆盖旧日志)。2>&1:把标准错误(stderr,比如git的错误提示)重定向到和标准输出一样的地方,这样错误信息也会被tee处理,同时显示在终端和写入日志。
方案二:把标准输出和错误输出分开存到不同文件
如果你想把正常输出和错误输出分别保存,同时终端还是能看到所有内容,可以这么写:
#!/bin/bash OUT_LOG="normal_output.log" ERR_LOG="error_output.log" # 处理stdout:终端+正常日志文件 exec > >(tee -a "$OUT_LOG") # 处理stderr:终端+错误日志文件,这里要把tee的输出重定向回stderr,保持终端的错误显示样式 exec 2> >(tee -a "$ERR_LOG" >&2) git pull origin main echo "Operation took XX minutes" # 其他命令...
注意事项:
- 确保脚本开头是
#!/bin/bash,因为进程替换>(...)是Bash的特性,sh(比如Dash)不支持这个语法。 - 如果不想追加日志,而是每次运行清空旧日志,去掉
tee的-a参数就行。 - 脚本里的子shell(比如
(cd /tmp && ls))也会继承这个重定向设置,所以子shell里的输出也会被捕获。
内容的提问来源于stack exchange,提问作者Dr. Gianluigi Zane Zanettini
相关产品推荐
相关产品推荐

