如何向stdout输出带颜色文本同时将无颜色内容追加到文件?
解决方案
核心问题是颜色控制码被同时输出到屏幕和日志文件,最优方案是拆分两个输出链路:纯无格式文本写入日志文件,带样式的内容单独输出到屏幕,无需额外工具过滤控制码,兼容性和可靠性最高。
优化后logger函数代码
function logger(){ GREEN=$(tput setaf 2) YELLOW=$(tput setaf 3) BOLD=$(tput bold) UNDERLINE=$(tput smul) NOCOLOR=$(tput sgr0) # 构造无格式纯文本内容,用于写入日志 raw_log="$(timestamp) $2\n" # 纯文本直接追加到日志文件,不输出到屏幕 echo -e -n "$raw_log" >> $log_file case "$1" in y) # 屏幕输出带黄色样式内容 echo -e -n "$(timestamp) ${YELLOW}$2 ${NOCOLOR}\n" ;; g) echo -e -n "$(timestamp) ${GREEN}$2 ${NOCOLOR}\n" ;; b) echo -e -n "$(timestamp) ${BOLD}$2 ${NOCOLOR}\n" ;; u) echo -e -n "$(timestamp) ${UNDERLINE}$2 ${NOCOLOR}\n" ;; n) # 无样式内容直接输出纯文本 echo -e -n "$raw_log" ;; *) echo "Unknown color!" ;; esac }
方案优势
- 完全兼容原有函数调用方式,无需修改现有业务代码
- 无需依赖sed/awk等额外工具,无额外性能开销
- 日志文件内容无任何冗余控制码,不会出现显示异常
- 适配所有常见shell运行环境
可选替代方案
如果需要保留tee的写法,可以在写入文件前过滤ANSI控制码,示例如下:
# 以y类输出为例,其余case同理修改即可 echo -e -n "$(timestamp) ${YELLOW}$2 ${NOCOLOR}\n" | tee /dev/tty | sed 's/\x1B\[[0-9;]*[JKmsu]//g' >> $log_file
该方案依赖sed工具,存在特殊控制码过滤不彻底的可能,优先级低于第一种方案。
内容的提问来源于stack exchange,提问作者Itai Ganot
相关产品推荐
相关产品推荐

