
Linux Shell 脚本的日志不是“随便 echo 一下就行”,而是要兼顾可读性、可追溯性、自动化处理和运维排查效率。核心原则是:时间明确、级别清晰、上下文完整、格式统一、输出可控。
日志必须带时间戳和级别标识
默认的 date 输出不够紧凑,建议用 ISO 8601 格式(如 2024-05-20T14:23:05+0800),并固定前缀标明级别(INFO/WARN/ERROR/DEBUG)。避免用颜色或特殊符号干扰日志解析。
- 推荐写法:
echo "$(date -u +%Y-%m-%dT%H:%M:%S%z) [INFO] Backup started for /var/log" - 封装成函数更稳妥,例如:
log() { local level=$1; shift; echo "$(date -u +%Y-%m-%dT%H:%M:%S%z) [$level] $*"; }log INFO "Processing user list"log ERROR "Failed to connect to DB: $?"
区分标准输出与错误输出,按需重定向
INFO/WARN 类日志走 stdout,ERROR/FATAL 必须走 stderr,这样便于用管道、重定向或日志收集器(如 rsyslog、filebeat)分离处理。
- 正确示例:
log ERROR "Config not found" >&2 - 运行脚本时可分离记录:
./backup.sh 2> backup.err | tee backup.log - 避免把所有日志都塞进 stdout,否则无法用
2>/dev/null抑制错误,也影响监控工具识别异常流
关键操作必须记录输入参数、返回码和执行耗时
一次失败的 cron 任务,如果没有上下文,几乎无法复现。启动时记参数,结束时记耗时和 exit code,能极大缩短排障时间。
- 开头记录:
log INFO "Script invoked with: $0 $*" - 命令后立刻检查:
if ! cp "$SRC" "$DST"; then log ERROR "cp failed (rc=$?)"; exit 1; fi - 计时建议用
BEGIN=$(date +%s.%N)+END=$(date +%s.%N); ELAPSED=$(echo "$END - $BEGIN" | bc),精度到毫秒
日志路径与轮转要脚本内控或依赖外部机制
不建议脚本自己做复杂轮转(如压缩、删除旧文件),容易出竞态或权限问题。优先使用系统级方案,脚本只负责写入固定路径。
- 推荐方式:脚本输出到
/var/log/myscript/latest.log,再由logrotate管理归档 - 若必须自管理,至少确保:
– 检查磁盘空间(df -h /var/log | awk 'NR==2 {print $5}' | sed 's/%//')
– 用find /var/log/myscript -name "*.log" -mtime +7 -delete控制保留天数
– 所有路径创建前先mkdir -p并校验写权限










