6.9.6 运维脚本规范与安全管理

运维脚本是数据库运维自动化的核心资产,应以“可读、可审、可控、可复用”为目标。统一规范能降低人为失误,提升协作效率,并满足审计要求。

原理草图:脚本规范与安全管理流程

文章图片

脚本命名与结构规范
- 采用“系统_功能_环境_版本”命名,如 mysql_backup_prod_v1.sh
- 统一目录结构:bin/(可执行)、conf/(配置)、lib/(函数库)、log/(日志)、docs/(说明)。

目录与模板示例(完整可执行骨架)

# 目录初始化
mkdir -p /opt/mysql-ops/{bin,conf,lib,log,docs}

# /opt/mysql-ops/bin/mysql_backup_prod_v1.sh
cat >/opt/mysql-ops/bin/mysql_backup_prod_v1.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail

# 作者: ops
# 版本: v1.0
# 用途: 备份MySQL并记录日志
# 依赖: mysql_config_editor, mysqldump
# 变更: 2024-01-01 init

BASE_DIR="/opt/mysql-ops"
CONF="${BASE_DIR}/conf/backup.conf"
LOG_FILE="${BASE_DIR}/log/backup_$(date +%F).log"

source "${BASE_DIR}/lib/common.sh"
load_conf "${CONF}"

log "INFO" "start backup for ${DB_NAME}"
require_env "DB_NAME" "BACKUP_DIR"

mkdir -p "${BACKUP_DIR}"
mysqldump --login-path=backup --single-transaction "${DB_NAME}" \
  | gzip >"${BACKUP_DIR}/${DB_NAME}_$(date +%F).sql.gz"

log "INFO" "backup ok, file=${BACKUP_DIR}/${DB_NAME}_$(date +%F).sql.gz"
EOF

# /opt/mysql-ops/lib/common.sh
cat >/opt/mysql-ops/lib/common.sh <<'EOF'
#!/usr/bin/env bash
log(){ printf "%s [%s] host=%s user=%s msg=%s\n" \
  "$(date +%F' '%T)" "$1" "$(hostname)" "${USER}" "$2" | tee -a "${LOG_FILE}"; }

load_conf(){ test -f "$1" || { echo "config missing: $1"; exit 1; }
  # shellcheck disable=SC1090
  source "$1"
}
require_env(){ for v in "$@"; do test -n "${!v:-}" || { echo "empty $v"; exit 1; }; done; }
EOF

# /opt/mysql-ops/conf/backup.conf
cat >/opt/mysql-ops/conf/backup.conf <<'EOF'
DB_NAME="appdb"
BACKUP_DIR="/data/backup/mysql"
EOF

chmod +x /opt/mysql-ops/bin/mysql_backup_prod_v1.sh

编码与可维护性要求
- 统一使用 Bash,严格模式:set -euo pipefail
- 关键操作参数化,禁止硬编码账号、路径与端口。
- 公共逻辑抽象为函数库,避免重复代码。

日志与审计格式示例

# 预期日志样例
# 2024-01-01 10:00:00 [INFO] host=db01 user=ops msg=start backup for appdb
# 2024-01-01 10:00:20 [INFO] host=db01 user=ops msg=backup ok, file=/data/backup/mysql/appdb_2024-01-01.sql.gz

权限与最小化原则(sudo 白名单)

# /etc/sudoers.d/mysql-ops
Cmnd_Alias MYSQL_OPS = /opt/mysql-ops/bin/mysql_backup_prod_v1.sh
ops ALL=(mysql) NOPASSWD: MYSQL_OPS
  • 禁止使用 root 直接执行数据库相关脚本。
  • MySQL 专用账户按脚本用途配置最小权限集。

凭据与密钥安全(推荐 mysql_config_editor)

# 安装/使用:MySQL 客户端自带
mysql_config_editor set --login-path=backup \
  --host=127.0.0.1 --user=backup --password

# 验证
mysql --login-path=backup -e "SELECT 1;"

安全执行与防误操作(dry-run 与环境识别)

# /opt/mysql-ops/bin/mysql_ddl_prod_v1.sh (片段)
ENV="${ENV:-prod}"
DRY_RUN="${DRY_RUN:-1}"

if [[ "${ENV}" == "prod" && "${DRY_RUN}" == "1" ]]; then
  echo "DRY-RUN: would execute DDL on prod"; exit 0
fi

发布与版本管理(Git 流程示例)

cd /opt/mysql-ops
git init
git add .
git commit -m "init mysql ops scripts"
git tag v1.0

合规与安全基线(自动检查工具安装与使用)

# 安装 shellcheck
# Ubuntu/Debian
apt-get update && apt-get install -y shellcheck
# CentOS/RHEL
yum install -y epel-release && yum install -y ShellCheck

# 检查脚本
shellcheck /opt/mysql-ops/bin/mysql_backup_prod_v1.sh

关键命令解释
- set -euo pipefail:遇到错误即退出、未定义变量报错、管道任一失败即失败。
- mysqldump --single-transaction:一致性备份,避免长锁。
- mysql_config_editor:在 ~/.mylogin.cnf 加密存储凭据。

排错清单
1. mysqldump: Got error: 1045
- 排查:mysql --login-path=backup -e "SELECT 1;"
- 修复:检查账号权限 SHOW GRANTS FOR 'backup'@'%';
2. config missing
- 排查:确认 /opt/mysql-ops/conf/backup.conf 是否存在、权限是否可读。
- 修复:chmod 640 /opt/mysql-ops/conf/backup.conf
3. 日志无输出
- 排查:LOG_FILE 是否可写,log 函数是否加载。
- 修复:确认 source /opt/mysql-ops/lib/common.sh

练习
1. 将备份脚本扩展为支持多库循环备份,要求参数 DB_LIST="db1 db2".
2. 增加 --dry-run 参数并输出将要生成的文件路径。
3. 为脚本增加 lock 文件机制,防止并发执行。