通用shell脚本模板

前言

自己在工作中,比较喜欢使用 shell 脚本来完成一些自动化的工作,毕竟作为程序员,能自动完成的就绝不手动完成。

每次自己临时写一个 shell 脚本,只为了完成业务逻辑。但有些通用的功能,每次都现写又觉得麻烦且费时,比如记录日志,解析脚本参数等。因此就想写一个通用的shell模板,提供基础且常用的功能,这样让自己只专注于编写业务逻辑,而不需要花费太多时间在基础通用功能上。


一个完整的 shell 脚本通常应该具备以下功能:

  • 具备完整的日志记录
  • 控制日志输出级别
  • 解析脚本参数
  • 在脚本结束时自动清理临时文件或目录
  • 输出彩色日志
  • 响应系统发出的各类信号
  • ...

脚本内容

  • 下面在自己写的一个shell模板,提供大家使用,有好的建议和写法欢迎在评论区分享。
#!/usr/bin/env bash
set -eEuo pipefail

# =========== 脚本说明 ===========
# 请修改工作目录 WORK_DIR 和日志文件 LOG_FILE
# 使用方式: ./template.sh 
# 参数: 
#  -v: 开启 debug 日志
#

# =========== 配置区域 ===========
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
readonly WORK_DIR="$SCRIPT_DIR"       # 工作目录
readonly LOG_FILE="$WORK_DIR/script.log"  # 日志文件


# =========== 主函数 ===========
function main() {
  # 切换到工作目录
  cd "$WORK_DIR" || die "无法进入目录: $WORK_DIR"
  
  # 业务逻辑
  log "业务逻辑开始"
  
  ls
  
  log -s "业务逻辑结束"
}

# =========== 清理函数 ===========
function cleanup() {
  # 清理临时文件、释放资源等
  # rm -f "$TEMP_FILE" 2>/dev/null || true
  if [[ ! -v ARGS_MAP["help"] ]]; then
    log "执行清理操作\n"
  fi
}

# =========== 工具函数 ===========
function die() {
  log -e "$1"
  exit "${2:-1}"
}

# =========== 解析参数 ===========
function parse_args(){
  # 参数列表MAP, 形如 [d] = "/path/dir"
  declare -gA ARGS_MAP
  while getopts ":vh" opt; do
    case "$opt" in 
      h) ARGS_MAP["help"]="true" ;;
      v) ARGS_MAP["debug"]="true" ;;
      \?) die "无效选项:$OPTARG" ;;
      :) die "选项 $OPTARG 缺少参数" ;;
    esac
  done
}

# =========== 打印帮助 ===========
function print_help_info(){
  echo "Usage: $0 [OPTIONS] [ARGS]"
  echo "Options:"
  echo " -h  显示帮助信息"
  echo " -v  显示脚本执行过程详细信息"
  echo " ...   其他待补充帮助信息"
}

# =========== 日志函数 ===========
# 使用方式:log -d "xxx"
function log() {
  
  if [[ "$#" -eq 0 ]]; then
    return 0
  fi
  
  local level="${1#-}"
  # 检测 LEVEL_MAP 是否存在键 level
  if [[ -v "LEVEL_MAP[$level]" ]]; then
    shift
  else
    level='i'   # 默认 INFO 级别
  fi
  
  # DEBUG 级别未开启
  if [[ "$level" == 'd' && ! -v "ARGS_MAP["debug"]" ]] ; then
    return 0
  fi
  # 构建日志行
  local log_line="[$(date '+%F %T.%3N')] [${LEVEL_MAP[$level]}] $*"
  
  # 只有 SUCCESS 作为输出,其他写入 stderr
  if [[ "$level" == 's' ]]; then
    echo -e "${COLOR_MAP[$level]}$log_line${COLOR_MAP['n']}"
  elif [[ -t 2 ]]; then
    echo -e "${COLOR_MAP[$level]}$log_line${COLOR_MAP['n']}" >&2
  else
    echo -e "$log_line" >&2
  fi
  
  # 写入日志文件
  echo -e "$log_line" >> "$LOG_FILE"
}

# ========= 初始化设置 =========s
function init() {
  # 颜色数组
  declare -gA COLOR_MAP
  if [[ -t 1 ]]; then
    COLOR_MAP=(
      [e]='\033[0;31m'   # Red
      [w]='\033[1;33m'   # Yellow
      [i]='\033[0m'    # No color
      [d]='\033[34m'   # Blue
      [s]='\033[0;32m'   # Green
      [n]='\033[0m'    # No color
    )
  fi
  
  # 日志级别
  declare -gA LEVEL_MAP=(
    [e]='ERROR'
    [w]='WARN'
    [i]='INFO'
    [d]='DEBUG'
    [s]='SUCCESS'
  )
  
  # 解析参数
  parse_args "$@"

  # 打印帮助信息
  if [[ -v ARGS_MAP["help"] ]]; then
    print_help_info
    exit 0
  fi

  log -d "检查工作目录"
  if [[ ! -d "$WORK_DIR" ]]; then
    die "工作目录不存在: $WORK_DIR"
  fi
  
  log -d "检查日志文件"
  if [[ ! -e "$LOG_FILE" ]]; then
    log -w "新建日志文件$LOG_FILE"
    touch "$LOG_FILE"
  fi
}

# =========== 信号处理 ===========
function handle_signal() {
  errorcode="$?"
  
  if [[ $errorcode -ne 0 ]]; then
    log -e "脚本非正常退出: 错误码: $errorcode, 行号: $LINENO, 命令: $BASH_COMMAND"
  elif [[ ! -v ARGS_MAP["help"] ]]; then
    log "脚本执行结束"
  fi
  
  # 执行清理
  cleanup
}


# =========== 信号捕获 ===========
trap 'handle_signal $? $LINENO $BASH_COMMAND' EXIT

# =========== 初始化  ===========

init "$@"
log -d "脚本初始化完成"

# ========= 执行主函数 ==========
main "$@"

内容解释

配置

  • 脚本中提供的配置区域,需要修改的是工作目录 WORK_DIR,默认是脚本所在的目录

  • 也可自定义脚本日志的输出路径 LOG_FILE

    BASH_SOURCEshell 脚本中的一个内置数组变量,表示 shell 脚本的调用层级。例如:outer.sh 内部执行 inner.sh,则 ${BASH_SOURCE[0]} 表示的是当前脚本名 inner.sh,而 ${BASH_SOURCE[1]} 表示调用的脚本名称 outer.sh。与 $0 区别是:$0 表示的是当前使用的 shell 名称(如bash, sh)。后面会专门出一期 shell 常见的内置变量。

主要函数

  • main() 中是写业务逻辑的地方。

  • cleanup() 中可以进行一些清理操作,比如删除临时文件。

  • parse_args() 中是一个解析脚本参数的函数,解析结果存入 ARGS_MAP 关联数组。getopts 是内置的一个专门用类解析参数的函数,只能处理短选项参数,但也足够用了。

  • print_help_info() 提供了脚本的帮助说明,如有需要可在此处扩展。

  • log() 提供了记录日志的功能。

    • 使用方式 log [-d] "xxx",提供了不同的日志级别(默认 info 级别),不同级别使用不同的颜色输出:
    • -e: error,红色
    • -w: warn,黄色
    • -i: info,无颜色
    • -d: debug,蓝色
    • -s: success,绿色(主要用于输出成功执行的日志信息)
  • init() 执行一些初始化操作:定义颜色数组,日志级别数组,前置检查等。

  • handle_signal() 处理操作系统的信号,脚本出现的运行错误会被 trap 捕获,自动定位错误的位置

  • 脚本先执行 init 函数,完成初始化准备工作,然后把脚本的参数全部传给 main 函数main "$@" 执行业务逻辑。

结束语

  • 这只是自己使用的脚本模板,分享出来希望能帮助到需要的同学。如有好的建议,欢迎评论区补充。
  • 欢迎大家关注我的微信公众号【扶锐随笔】
    3f30b7eef45e37ccfa179b30e3123322
posted @ 2026-07-16 22:38  九原鹰  阅读(1)  评论(0)    收藏  举报