You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Bourne Shell脚本日志同时输出至文件与控制台?

在Bourne Shell(/bin/sh)中实现日志同时输出到文件和控制台

Bash里的exec &> >(tee -a "$log")依赖进程替换(>(...)语法),但Bourne Shell(/bin/sh)不支持这个特性,需要用文件描述符或管道的方式替代。

方法一:使用命名管道(mkfifo)

这是兼容性最好的方案,几乎所有POSIX兼容的/bin/sh都支持:

#!/bin/sh
log="mylog.log"

# 创建临时命名管道
log_pipe="/tmp/$(basename "$0").pipe"
mkfifo "$log_pipe"

# 启动tee:从管道读取内容,同时追加到日志文件并输出到控制台
tee -a "$log" < "$log_pipe" &
tee_pid=$!

# 将当前Shell的标准输出和标准错误都重定向到管道
exec > "$log_pipe" 2>&1

# 脚本退出时自动清理管道和tee进程
trap 'kill "$tee_pid" 2>/dev/null; rm -f "$log_pipe"' EXIT

说明:

  • mkfifo创建命名管道,作为Shell输出和tee的中转通道
  • 后台启动的tee从管道读取内容,同时完成日志追加和控制台输出
  • exec > "$log_pipe" 2>&1把当前Shell的所有输出(包括标准错误)都定向到管道
  • trap语句确保脚本退出时清理临时文件和后台进程,避免残留垃圾

方法二:使用文件描述符复制

如果不想创建临时文件,也可以通过文件描述符复制实现:

#!/bin/sh
log="mylog.log"

# 保存原始的标准输出(fd1)到fd3,标准错误(fd2)到fd4
exec 3>&1 4>&2

# 启动tee:读取标准输入,同时写入日志和原始控制台,错误输出转原始标准错误
tee -a "$log" >&3 2>&4 &
tee_pid=$!

# 将当前Shell的标准输出和错误都重定向到tee的标准输入
exec >&0 2>&1

# 退出时清理tee进程
trap 'kill "$tee_pid" 2>/dev/null' EXIT

说明:

  • 先保存原始控制台的输出描述符,避免tee无法输出到控制台
  • 后台运行的tee负责将输入内容同时写入日志和原始控制台
  • 最后把Shell的所有输出重定向到tee的输入,实现双端输出

内容的提问来源于stack exchange,提问作者flymg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 13:43:14