← 中文资源

简体中文版本

Bash 日志函数分级输出

用日志函数组织脚本输出:四级过滤随 LOG_LEVEL 切换、错误警告走 stderr 与正常输出分离、时间戳统一前缀。

阅读英文原文

示例说明

echo 散落各处的脚本无法运维:信息混在 stdout、错误没有级别、管道重定向时日志跟着数据流走丢。logger 函数收拢三点:级别作为第一个参数,debug 级受环境变量开关控制;error 与 warn 定向 stderr——stdout 留给真实数据,2>/dev/null 或 2>&1 的重定向选择权交给调用方;时间戳前缀让输出自带时间线。

技术要点

  • 级别参数化并支持过滤
  • 错误与警告定向 stderr
  • 时间戳统一格式前缀

代码解读

log 的 case 分支决定目标流,printf 的三段式输出时间戳、大写级别、消息;log_debug 用算术短路实现可关断——VERBOSE 为零时 or true 兜住返回值防 -e 误杀。main 演示四级的典型用法:目录缺失是 error 并返回失败,空间不足是 warn 但继续。

使用建议

颜色输出要检测 tput 或终端存在性,管道下自动关闭。更复杂需求直接用 logger 命令接入 syslog。脚本输出与数据输出的分离是管道化复用的前提。

代码示例

#!/usr/bin/env bash
set -euo pipefail

readonly LOG_LEVEL="${LOG_LEVEL:-info}"
declare -i VERBOSE=0
[[ "${LOG_LEVEL}" == "debug" ]] && VERBOSE=1

_timestamp() { date +'%Y-%m-%dT%H:%M:%S'; }

log() {
  local level="$1"
  shift
  local target=stdout

  case "${level}" in
    error) target=stderr ;;
    warn)  target=stderr ;;
  esac

  local prefix="[ ${level^^} ]"
  printf '%s %s %s\n' "$(_timestamp)" "${prefix}" "$*" >&"${target}"
}

log_debug() { (( VERBOSE )) && log debug "$@" || true; }
log_info()  { log info "$@"; }
log_warn()  { log warn "$@"; }
log_error() { log error "$@"; }

main() {
  log_info "开始同步目录 ${SYNC_DIR:-./data}"
  log_debug "参数列表: ${*}"

  if [[ ! -d "${SYNC_DIR:-./data}" ]]; then
    log_error "同步目录不存在,中止"
    return 1
  fi

  log_warn "磁盘剩余空间低于阈值,继续执行"
  log_info "同步完成"
}

log_debug "脚本启动于 PID $$"
main "$@"