运维利器:实战自动化脚本分享,告别“人肉运维”
运维利器:实战自动化脚本分享,告别“人肉运维”
在IT运维的日常工作中,面对成百上千台服务器和繁杂重复的任务,纯靠“人肉运维”不仅效率低下,且极易因人为疏忽导致线上事故。自动化运维不仅是提升效率的利器,更是保障系统稳定性的关键。
本文将结合实际工作场景,分享几款经过实战检验的Shell与Python自动化脚本,涵盖日志清理、服务自愈、资产巡检与数据备份,帮助大家从繁琐的机械操作中解放出来。
一、 Shell脚本:按天轮转与清理历史日志
磁盘空间告警是运维常遇的痛点,尤其是应用服务产生的日志文件,若不加以清理极易撑爆磁盘。手动清理费时费力,下面这个Shell脚本通过find命令结合时间戳,实现日志的自动压缩与清理。
#!/bin/bash
# 描述:自动压缩指定天数前的日志,并删除指定天数前的压缩包
# 作者:运维自动化系列
LOG_DIR="/data/app/logs"
# 7天前的日志进行压缩
COMPRESS_DAYS=7
# 30天前的压缩包进行删除
DELETE_DAYS=30
echo "===== 开始执行日志清理任务: $(date '+%Y-%m-%d %H:%M:%S') ====="
# 1. 压缩7天前的.log文件
find ${LOG_DIR} -name "*.log" -type f -mtime +${COMPRESS_DAYS} -exec gzip {} \;
echo "已压缩超过 ${COMPRESS_DAYS} 天的日志文件。"
# 2. 删除30天前的.gz压缩包
find ${LOG_DIR} -name "*.gz" -type f -mtime +${DELETE_DAYS} -exec rm -f {} \;
echo "已删除超过 ${DELETE_DAYS} 天的压缩日志。"
echo "===== 日志清理任务执行完毕 ====="
实战解析:
此脚本巧妙运用了find命令的-mtime参数。+7表示查找修改时间在7天之前的文件。先压缩再删除的策略,既释放了近期磁盘空间,又保留了相对久远的日志以备查,在空间与安全之间取得了平衡。建议配合Crontab每日凌晨执行。
二、 Shell脚本:核心服务健康检查与自愈
服务假死或异常宕机是另一大运维噩梦。对于未部署专业监控自愈系统(如K8s)的传统服务,可以通过定时脚本探测端口存活状态,一旦发现异常立即重启并告警。
#!/bin/bash
# 描述:监控服务端口,异常时自动重启并触发告警
SERVICE_NAME="my-core-service"
PORT=8080
WEBHOOK_URL="https://hooks.example.com/alert"
# 检测端口是否存活
check_port() {
/usr/sbin/ss -tlnp | grep -q ":${PORT} "
return $?
}
# 发送告警
send_alert() {
curl -s -X POST "${WEBHOOK_URL}" \
-H 'Content-Type: application/json' \
-d "{\"content\": \"【严重告警】${SERVICE_NAME} 端口 ${PORT} 异常,已尝试自动重启!\"}" > /dev/null
}
# 主逻辑
if ! check_port; then
echo "$(date): ${SERVICE_NAME} 端口 ${PORT} 不通,尝试重启..." >> /var/log/service_monitor.log
systemctl restart ${SERVICE_NAME}
sleep 5 # 等待5秒让服务启动
if ! check_port; then
echo "$(date): ${SERVICE_NAME} 重启失败,需人工介入!" >> /var/log/service_monitor.log
send_alert
else
echo "$(date): ${SERVICE_NAME} 重启成功,端口恢复。" >> /var/log/service_monitor.log
fi
fi
实战解析:
脚本使用ss命令检测端口,比netstat更高效。发现异常后先执行systemctl restart,休眠5秒后再次检测,若依然失败则通过Webhook(如钉钉/企微机器人)发送告警。这种“先自愈,后告警”的思路,能在大半夜帮你挡掉80%的非业务逻辑级故障。
三、 Python脚本:基于psutil的系统资产巡检
当服务器数量增多,手动登录每台机器执行top、df查看资源变得不现实。Python的psutil库是跨平台的系统监控利器,能轻松采集CPU、内存、磁盘等核心指标。
#!/usr/bin/env python3
# 描述:采集系统核心资源指标并输出JSON格式,便于对接CMDB或监控系统
import psutil
import json
from datetime import datetime
def get_system_info():
info = {
"timestamp": datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
"cpu": {
"logical_count": psutil.cpu_count(logical=True),
"usage_percent": psutil.cpu_percent(interval=1)
},
"memory": {
"total_gb": round(psutil.virtual_memory().total / (1024**3), 2),
"used_gb": round(psutil.virtual_memory().used / (1024**3), 2),
"usage_percent": psutil.virtual_memory().percent
},
"disk": []
}
# 采集磁盘使用率(仅采集挂载点)
for part in psutil.disk_partitions():
if 'cdrom' in part.opts or part.fstype == '':
continue
usage = psutil.disk_usage(part.mountpoint)
info["disk"].append({
"mountpoint": part.mountpoint,
"total_gb": round(usage.total / (1024**3), 2),
"used_percent": usage.percent
})
return info
if __name__ == "__main__":
system_info = get_system_info()
# 以JSON格式输出,方便后续程序解析
print(json.dumps(system_info, indent=4, ensure_ascii=False))
实战解析:
相比于Shell的awk/grep拼凑,Python代码具备极强的可读性和扩展性。输出标准化JSON格式,使得该脚本不仅能单机运行,还能作为Agent被Ansible或SSH批量调用,将结果汇总至中央数据库,构建轻量级CMDB巡检系统。
四、 Python脚本:MySQL定时逻辑备份与空间轮转
数据库是公司的生命线,备份重于泰山。虽然物理备份(XtraBackup)更受欢迎,但对于中小型库,逻辑备份依然简单有效。以下脚本实现数据库Dump、压缩及旧备份清理。
#!/usr/bin/env python3
# 描述:MySQL逻辑备份,压缩存储并清理过期备份
import os
import subprocess
import datetime
import glob
# 配置项
DB_HOST = "127.0.0.1"
DB_USER = "backup_user"
DB_PASS = "YourStrongPassword" # 建议从环境变量或Vault读取
BACKUP_DIR = "/data/backups/mysql"
KEEP_DAYS = 7
def perform_backup():
# 确保备份目录存在
os.makedirs(BACKUP_DIR, exist_ok=True)
date_str = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
sql_file = os.path.join(BACKUP_DIR, f"all_dbs_{date_str}.sql")
gz_file = f"{sql_file}.gz"
# 执行mysqldump
dump_cmd = f"mysqldump -h{DB_HOST} -u{DB_USER} -p{DB_PASS} --all-databases --single-transaction > {sql_file}"
try:
subprocess.run(dump_cmd, shell=True, check=True, stderr=subprocess.PIPE)
# 压缩备份文件
subprocess.run(f"gzip {sql_file}", shell=True, check=True)
print(f"备份并压缩成功: {gz_file}")
# 清理KEEP_DAYS前的备份
cutoff_time = datetime.datetime.now() - datetime.timedelta(days=KEEP_DAYS)