linux运维脚本中输出带时间戳的错误日志,关键用ts或stdbuf+awk为stderr添加时间戳,并结合$lineno、$?、${bash_source[0]}记录行号、退出码和文件位置,再统一写入带轮转的指定日志文件。

在Linux运维脚本中输出带时间戳的详细错误日志,关键是把标准错误(stderr)重定向到一个能自动添加时间戳的日志流中,同时保留错误上下文(如行号、命令、退出码等)。
用 ts 命令为 stderr 添加时间戳
ts 是 moreutils 工具包里的小工具,专为给流加时间戳设计,格式简洁、开销低。先确认已安装:
sudo yum install moreutils # CentOS/RHEL(需 EPEL)
然后在脚本中这样用:
#!/bin/bash exec 2> >(ts '[%Y-%m-%d %H:%M:%S]' >&2) ls /nonexistent 2>&1 || echo "命令失败"
执行后 stderr 每行都会带上类似 [2024-05-20 14:22:03] ls: cannot access '/nonexistent': No such file or directory 的前缀。
用 stdbuf + awk 实现更灵活的时间格式
如果系统没装 moreutils,可用 awk 自建时间戳管道。注意要配合 stdbuf -oL -eL 强制行缓冲,避免 stderr 缓存导致时间错乱:
- 将脚本 stderr 实时送入带时间戳的 awk 处理:
exec 2> >(stdbuf -oL -eL awk '{print "[" strftime("%F %T") "] ERROR:" $0}' >&2)
这会输出类似:[2024-05-20 14:22:03] ERROR: ls: cannot access '/nonexistent': No such file or directory
- 支持自定义前缀(如 “ERROR”、“WARN”),也方便后续用
grep ERROR过滤。
记录错误时附带上下文信息
光有时间不够,运维定位问题还需知道“在哪出的错”。可在关键命令后手动补全上下文:
- 用
$LINENO记录出错行号: - 用
$?捕获上条命令退出码; - 用
${BASH_SOURCE[0]}:$LINENO标明文件和位置。
示例写法:
if ! cp /src/file.txt /dst/; then
echo "[$(date '+%F %T')] ERROR: cp failed at ${BASH_SOURCE[0]}:$LINENO, exit code $?" >&2
fi
统一日志路径 + 轮转建议
错误日志别直接打屏,应写入指定文件并考虑轮转:
- 用
exec 2>> /var/log/myscript.err.log追加到文件; - 配合
logrotate配置按天切分、保留7天,防止撑爆磁盘; - 若脚本多实例并发运行,可用
$$(进程 PID)区分日志文件名,例如:/var/log/myscript.err.$$.log。











