从入门到自动化运维
目录导读
- 为什么需要环境检测与修复脚本?
- 核心设计原则:检测-修复-验证闭环
- 基础检测命令与日志采集技巧
- 条件判断与异常处理机制
- 自动修复策略与回滚方案
- 定时任务与监控告警集成
- 实战案例:数据库空间不足自动清理
- 常见问题与安全加固建议
为什么需要环境检测与修复脚本?
在运维与DevOps实践中,环境故障(如磁盘写满、服务宕机、依赖缺失)往往造成业务中断。人工排查耗时且易遗漏,而脚本化处理能实现:

- 秒级响应:通过cron或systemd timer定时触发,替代人工巡检
- 一致性修复:避免不同工程师操作差异导致的新问题
- 审计可追溯:每次修复动作记录日志,便于复盘
问:脚本检测与监控工具(如Zabbix)有何区别? 答:监控工具负责“发现异常并告警”,而修复脚本则聚焦“自动处置并恢复”,两者互补,脚本应作为监控告警后的最后一道自动防线。
核心设计原则:检测-修复-验证闭环
优秀的修复脚本不能只“做了”,还要“确认做对了”,遵循以下三步闭环:
graph LR A[检测] -->|异常触发| B[修复] B --> C[验证] C -->|未恢复| B C -->|恢复成功| D[记录日志并退出]
关键点:
- 幂等性:修复操作无论执行几次,结果一致(确保目录存在”而非“创建目录”)
- 超时控制:防止修复命令本身卡死(使用
timeout 10包裹) - 分级处理:轻故障尝试自动修复,重故障停止操作并报警
基础检测命令与日志采集技巧
不同环境的检测命令需封装为函数,便于复用,以Bash为例:
check_disk_usage() {
local threshold=$1 # 如 85
local usage=$(df / | awk 'NR==2 {print $5}' | sed 's/%//')
if [ $usage -gt $threshold ]; then
echo "WARN: Disk usage ${usage}% exceeds ${threshold}%"
return 1
else
echo "INFO: Disk usage ${usage}% normal"
return 0
fi
}
日志采集:
- 统一使用
logger或tee -a /var/log/env_repair.log - 记录时间戳、执行用户、退出码
- 建议采用JSON格式,便于ELK等系统解析
条件判断与异常处理机制
脚本必须区分“可修复”与“不可修复”场景,建议采用状态机模式:
def main():
state = "check"
while state != "exit":
if state == "check":
state = "repair" if is_broken() else "exit"
elif state == "repair":
state = "verify" if attempt_repair() else "alert"
elif state == "verify":
state = "exit" if is_healthy() else "repair"
elif state == "alert":
send_sms("人工介入")
state = "exit"
陷阱提醒:
- 避免
set -e导致未知错误提前退出;建议使用set +e后用判断 - 修复动作前必须备份原配置(如
cp /etc/app.conf /etc/app.conf.bak)
自动修复策略与回滚方案
修复策略应遵循“最小权限”和“渐进式修复”原则:
| 级别 | 策略 | 示例 |
|---|---|---|
| L1 | 无副作用操作 | 清理临时文件、重启服务 |
| L2 | 需谨慎操作 | 修改配置文件、删除旧日志 |
| L3 | 高影响操作 | 重装软件包、格式化分区(需人工确认标志文件存在) |
回滚机制:
# 修复前 cp /opt/myapp/config.ini /opt/myapp/config.ini.$(date +%s) # 若验证失败 mv /opt/myapp/config.ini.bak /opt/myapp/config.ini systemctl restart myapp
定时任务与监控告警集成
将脚本接入cron(注意环境变量PATH):
*/5 * * * * /usr/local/bin/env_check.sh >> /var/log/env_repair.log 2>&1
告警集成:脚本执行异常退出码(如2)时,通过webhook推送至钉钉/企业微信:
if exit_code != 0:
requests.post(webhook_url, json={"msg": f"修复失败,需人工介入"})
实战案例:数据库空间不足自动清理
场景:MySQL binlog占满磁盘,导致服务不可写。
脚本核心代码(Python伪代码):
import shutil, subprocess
def get_mysql_data_disk_usage():
return shutil.disk_usage("/var/lib/mysql")
def purge_binlog():
subprocess.run(["mysql", "-e", "PURGE BINARY LOGS BEFORE NOW() - INTERVAL 3 DAY;"])
def main():
if get_mysql_data_disk_usage().percent > 85:
print("Disk usage > 85%, purging old binlogs...")
purge_binlog()
# 验证
if get_mysql_data_disk_usage().percent < 60:
print("Recovery successful")
else:
raise Exception("Purge failed, consider archive logic")
关键细节:binlog_expire_logs_seconds与手动清理结合,避免误删在线日志。
常见问题与安全加固建议
常见错误:
- ❌ 脚本中硬编码IP和密码(应使用环境变量或密钥管理服务)
- ❌ 无限重试导致负载飙升(应设最大重试次数,如3次)
- ❌ 忽略系统dependencies(如
bc、jq未安装)
加固建议:
- 使用
shellcheck静态分析脚本语法 - 脚本内嵌入版本号(如
VERSION=1.2.0)便于追踪 - 关键操作前检查
run_lock文件防止并发执行 - 对输出进行脱敏(避免打印密码、token)
Q&A 精华汇总:
- 问:脚本用Bash还是Python? 答:简单检查用Bash(依赖少);复杂逻辑如正则匹配、操作数据库用Python(可读性强)。
- 问:如何测试脚本可靠性? 答:采用Docker模拟故障环境,配合
fault injection工具(如tc模拟网络丢包)进行混沌测试。
环境检测与修复脚本是运维的“自动驾驶仪”,其核心在可靠性与控制风险之间平衡,建议从简单场景(磁盘空间)入手,逐步覆盖服务、网络、依赖等层面,最后提醒:任何自动修复都无法替代完善的备份策略——修复之前,先保住数据。