运维脚本需工程化:命名规范(功能+环境+角色)、标准目录结构(bin/lib/conf/log/tests)、健壮性设计(set -euo pipefail、路径校验、参数验证)、结构化日志(带时间戳/级别/脱敏)、CI/CD集成(Git管理+Ansible分发)、最小权限与定期审计。

写运维脚本不是“能跑就行”,而是要可读、可维护、可复用、可审计。工程化不是给简单脚本套大词,是建立一套让团队协作顺畅、故障快速定位、变更安全可控的实践习惯。
命名与结构:让脚本一眼看懂“它该干什么”
脚本名不叫 a.sh 或 bak.sh,而应体现功能+环境+角色,例如:
backup_mysql_prod_daily.sh(生产环境每日 MySQL 备份)
check_disk_alert_staging.sh(预发环境磁盘告警检查)
标准目录结构建议(以项目为单位):
- bin/:主执行脚本(带可执行权限)
- lib/:通用函数库(如日志封装、配置加载、网络检测)
- conf/:环境配置文件(prod.conf、staging.conf),不硬编码敏感信息
- log/:运行日志(按日期轮转,避免单文件爆炸)
- tests/:简单校验逻辑(如“执行前检查 mysqld 是否存活”)
健壮性设计:别让脚本在半夜把你叫醒
真实运维场景中,失败往往发生在边界条件:磁盘满、权限不足、服务未启动、命令不存在、网络超时。脚本必须主动防御:
- 开头统一设置:
set -euo pipefail(遇错中断、未定义变量报错、管道任一环节失败即退出) - 关键命令后加判断:
[[ $? -eq 0 ]] || { echo "备份失败" >&2; exit 1; } - 路径操作前先
cd /path && [[ $? -eq 0 ]] || die "进入目录失败",不假设当前工作目录 - 使用绝对路径调用命令(
/usr/bin/find而非find),避免 PATH 污染导致行为异常 - 对输入参数做合法性校验(如时间格式、IP 格式、文件存在性),拒绝“带病运行”
日志与可观测性:出问题时,第一行日志就该告诉你发生了什么
不要只靠 echo,要结构化记录:
- 每条日志带时间戳、脚本名、级别(INFO/WARN/ERROR)、上下文(如操作对象、PID)
- 错误输出重定向到
&2,正常输出走&1,方便管道和重定向分离 - 敏感信息(密码、token、密钥路径)必须脱敏,禁止明文出现在日志中
- 关键步骤前后打点,例如:
log_info "开始压缩 /var/log/nginx/"; tar -czf ...; log_info "压缩完成,大小 $(du -h archive.tgz | awk '{print $1}')" - 日志文件按天切割,保留最近 7 天,超期自动清理(可用
logrotate或脚本内find log/ -name "*.log" -mtime +7 -delete)
部署与协作:脚本不是孤岛,要融入 CI/CD 和权限体系
运维脚本上线 ≠ scp 到服务器 chmod +x:
- 所有脚本纳入 Git 管理,分支策略清晰(
main对应生产,dev用于测试,提交需 PR + 至少一人 review) - 通过 Ansible / SaltStack / 自建部署工具分发,确保一致性;禁止手工拷贝
- 执行权限最小化:脚本由专用运维用户(如
ops)运行,该用户仅拥有必要 sudo 权限(如sudoers中限定为NOPASSWD: /usr/local/bin/backup_*.sh) - 定期审计脚本变更:用
git log -p --since="30 days ago" -- bin/ lib/快速回溯风险操作 - 提供简易帮助:
./script.sh -h输出用法、参数说明、示例,降低新成员上手成本










