Shell 编程规范 & 运维脚本模板

Shell 编程规范 & 运维脚本模板

会写 Shell,和写好 Shell,是两回事。

真正出问题的,往往不是“语法错误”, 而是:

  • 脚本不规范
  • 变量混乱
  • 没有容错
  • 出事不好排查

一、为什么运维必须讲 Shell 规范?

真实事故来源👇

  • rm 少了目录校验
  • 脚本失败却继续执行
  • 日志没打,事后无法追溯
  • 同事接手脚本完全看不懂

📌 结论一句话

Shell 脚本 = 代码 代码 = 必须有规范


二、Shell 脚本通用规范(强烈建议)

1️⃣ 必须指定解释器

1
#!/bin/bash

❌ 禁止省略 ❌ 禁止依赖环境猜测


2️⃣ 开头统一开启安全模式

1
set -euo pipefail

含义说明:

参数 作用
-e 命令失败立即退出
-u 使用未定义变量直接报错
-o pipefail 管道中任一失败即失败

👉 生产脚本强烈建议开启


3️⃣ 脚本必须写说明注释

1
2
3
4
5
6
7
# ------------------------------------------------------------------
# 脚本名称: backup_mysql.sh
# 功能描述: MySQL 数据库定时备份
# 作者: 运维部
# 创建时间: 2025-xx-xx
# 使用说明: ./backup_mysql.sh
# ------------------------------------------------------------------

📌 不是给自己看的,是给“接盘的人”看的


三、变量命名规范(非常重要)

1️⃣ 全局变量:全部大写

1
2
BACKUP_DIR="/data/backup"
LOG_FILE="/var/log/backup.log"

2️⃣ 局部变量:小写 + local

1
2
3
backup_db() {
local db_name=$1
}

❌ 禁止函数里直接用全局变量当临时变量


3️⃣ 常量使用 readonly

1
readonly SCRIPT_NAME=$(basename "$0")

四、路径 & 变量的安全写法

1️⃣ 所有变量都要加引号

1
rm -rf "$DIR"

❌ 错误写法:

1
rm -rf $DIR

👉 防止空变量导致误删 /


2️⃣ 重要目录操作前必须校验

1
[ -d "$BACKUP_DIR" ] || mkdir -p "$BACKUP_DIR"

五、函数使用规范

1️⃣ 所有逻辑必须进函数

❌ 不推荐:

1
2
echo "开始备份"
mysqldump ...

✅ 推荐:

1
2
3
4
main() {
echo "开始备份"
backup_mysql
}

2️⃣ main 函数统一入口

1
main "$@"

📌 让脚本结构一眼就能看懂


六、日志规范(运维脚本灵魂)

1️⃣ 标准日志函数

1
2
3
log() {
echo "$(date '+%F %T') [$1] $2" | tee -a "$LOG_FILE"
}

调用:

1
2
log INFO "备份开始"
log ERROR "备份失败"

2️⃣ 禁止裸 echo 关键信息

1
echo "失败了"

1
log ERROR "数据库备份失败"

七、错误处理规范

1️⃣ 必须捕获异常退出

1
trap 'log ERROR "脚本异常退出"; exit 1' ERR

2️⃣ 主动判断关键命令

1
2
3
4
if ! mysqldump ...; then
log ERROR "mysqldump 执行失败"
exit 1
fi

八、参数校验规范

示例:校验参数个数

1
2
3
4
if [ $# -ne 1 ]; then
echo "Usage: $0 <backup_dir>"
exit 1
fi

👉 永远不要假设用户会正确使用脚本


九、运维通用 Shell 脚本模板(可直接用)

📌 这是整篇文章的核心,建议直接收藏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!/bin/bash
set -euo pipefail

# ================== 基本信息 ==================
SCRIPT_NAME=$(basename"$0")
LOG_FILE="/var/log/${SCRIPT_NAME}.log"
readonly SCRIPT_NAME
readonly LOG_FILE

# ================== 日志函数 ==================
log() {
local level=$1
local msg=$2
echo"$(date '+%F %T') [$level] $msg" | tee -a "$LOG_FILE"
}

# ================== 错误捕获 ==================
trap'log ERROR "脚本执行异常,已退出"; exit 1' ERR

# ================== 功能函数 ==================
check_env() {
log INFO "检查运行环境"
command -v tar >/dev/null || { log ERROR "tar 未安装"; exit 1; }
}

backup_data() {
local src="/data"
local dst="/backup/data_$(date +%F).tar.gz"

log INFO "开始备份 $src"
tar czf "$dst""$src"
log INFO "备份完成:$dst"
}

# ================== 主函数 ==================
main() {
check_env
backup_data
log INFO "脚本执行完成"
}

main "$@"

👉 这套结构,适用于 90% 运维脚本


十、生产环境 Shell 编程黄金法则

📌 记住这 5 条:

1️⃣ 所有脚本都能反复执行 2️⃣ 所有关键操作都有日志 3️⃣ 所有变量都有保护 4️⃣ 所有失败都能立刻退出 5️⃣ 所有人接手都能看懂