# 做了 16 年运维,我用这 5 个 Python 脚本把加班时间减少了 80%

4 阅读11分钟

建议先收藏⭐,用到的时候随时能找到


做了 16 年运维,我从手动操作到全自动化,深刻体会到:好的工具能让运维效率提升 10 倍。

35 岁后,我明显感觉到体力跟不上:

  • 半夜 3 点被告警电话叫醒,强撑着登录服务器排查
  • 周末加班 5 小时,只为给 50 台服务器打补丁
  • 同样的操作重复几百次,感觉自己像个机器人

直到我开始用 Python 写自动化脚本,情况彻底改变:

  • ✅ 服务器检查从 2 小时变成 5 分钟
  • ✅ 部署发布从手动操作变成一键完成
  • ✅ 半夜告警从每周 3 次变成每月 1 次

今天分享 5 个我工作中最常用的自动化脚本,代码全部开源,帮你从重复劳动中解放出来,准时下班陪家人。


一、日志自动分析脚本

场景

每天需要分析 Nginx 日志,找出访问异常的 IP 和 URL

传统做法

用 grep、awk 手动分析,花 30 分钟

自动化方案

#!/usr/bin/env python3
"""
Nginx 日志分析脚本
功能:提取访问 TOP10 的 IP、URL,识别异常请求
"""
import re
from collections import Counter
from datetime import datetime

def analyze_nginx_log(log_file, top_n=10):
    """分析 Nginx 日志"""
    
    # 正则表达式匹配日志行
    log_pattern = r'(\d+\.\d+\.\d+\.\d+).*?"(GET|POST|PUT|DELETE)\s+([^\s]+).*?"\s+(\d{3})'
    
    ip_counter = Counter()
    url_counter = Counter()
    error_requests = []
    
    with open(log_file, 'r', encoding='utf-8') as f:
        for line in f:
            match = re.search(log_pattern, line)
            if match:
                ip, method, url, status = match.groups()
                ip_counter[ip] += 1
                url_counter[url] += 1
                
                # 记录错误请求(4xx 和 5xx)
                if status.startswith(('4', '5')):
                    error_requests.append({
                        'ip': ip,
                        'method': method,
                        'url': url,
                        'status': status,
                        'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                    })
    
    # 输出结果
    print("=" * 60)
    print(f"📊 Nginx 日志分析报告")
    print("=" * 60)
    
    print(f"\n🔝 访问 TOP{top_n} IP:")
    for ip, count in ip_counter.most_common(top_n):
        print(f"  {ip}: {count} 次")
    
    print(f"\n🔝 访问 TOP{top_n} URL:")
    for url, count in url_counter.most_common(top_n):
        print(f"  {url}: {count} 次")
    
    print(f"\n⚠️ 错误请求数:{len(error_requests)}")
    if error_requests:
        print("\n最近 5 条错误请求:")
        for req in error_requests[:5]:
            print(f"  [{req['status']}] {req['method']} {req['url']} (IP: {req['ip']})")
    
    return {
        'top_ips': ip_counter.most_common(top_n),
        'top_urls': url_counter.most_common(top_n),
        'error_count': len(error_requests),
        'errors': error_requests
    }

if __name__ == '__main__':
    analyze_nginx_log('/var/log/nginx/access.log')

效果

30 秒出报告,效率提升 60 倍

进阶用法

  • 定时执行(cron 每天凌晨 2 点)
  • 邮件发送报告
  • 异常 IP 自动封禁

二、服务器健康检查脚本

场景

管理 50+ 台服务器,每天需要检查 CPU、内存、磁盘

传统做法

登录每台服务器执行 top、df 命令,花 1 小时

自动化方案

#!/usr/bin/env python3
"""
服务器健康检查脚本
功能:批量检查服务器资源使用情况,自动告警
"""
import paramiko
import json
from datetime import datetime

# 服务器列表
SERVERS = [
    {'host': '192.168.1.10', 'username': 'root', 'password': 'xxx'},
    {'host': '192.168.1.11', 'username': 'root', 'password': 'xxx'},
    # ... 更多服务器
]

# 告警阈值
THRESHOLDS = {
    'cpu': 80,    # CPU 使用率 > 80% 告警
    'memory': 85, # 内存使用率 > 85% 告警
    'disk': 90    # 磁盘使用率 > 90% 告警
}

def check_server(server):
    """检查单台服务器"""
    try:
        # SSH 连接
        client = paramiko.SSHClient()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        client.connect(
            hostname=server['host'],
            username=server['username'],
            password=server['password'],
            timeout=5
        )
        
        # 执行检查命令
        commands = {
            'cpu': "top -bn1 | grep 'Cpu(s)' | awk '{print $2 + $4}'",
            'memory': "free | grep Mem | awk '{printf \"%.2f\", $3/$2 * 100}'",
            'disk': "df -h / | tail -1 | awk '{print $5}' | tr -d '%'"
        }
        
        result = {'host': server['host'], 'status': 'OK', 'alerts': []}
        
        for metric, cmd in commands.items():
            stdin, stdout, stderr = client.exec_command(cmd)
            value = float(stdout.read().decode().strip())
            result[metric] = value
            
            # 检查是否超过阈值
            if value > THRESHOLDS[metric]:
                result['alerts'].append(f"{metric.upper()} 使用率过高:{value}%")
                result['status'] = 'WARNING'
        
        client.close()
        return result
        
    except Exception as e:
        return {
            'host': server['host'],
            'status': 'ERROR',
            'error': str(e)
        }

def health_check_all():
    """检查所有服务器"""
    print("=" * 60)
    print(f"🏥 服务器健康检查报告 - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print("=" * 60)
    
    results = []
    for server in SERVERS:
        result = check_server(server)
        results.append(result)
        
        # 打印结果
        status_icon = {'OK': '✅', 'WARNING': '⚠️', 'ERROR': '❌'}
        print(f"\n{status_icon.get(result['status'], '❓')} {result['host']}")
        
        if result['status'] == 'OK':
            print(f"  CPU: {result.get('cpu', 'N/A')}% | 内存:{result.get('memory', 'N/A')}% | 磁盘:{result.get('disk', 'N/A')}%")
        elif result['status'] == 'WARNING':
            for alert in result['alerts']:
                print(f"  ⚠️ {alert}")
        else:
            print(f"  错误:{result.get('error', '未知错误')}")
    
    # 统计
    ok_count = sum(1 for r in results if r['status'] == 'OK')
    warning_count = sum(1 for r in results if r['status'] == 'WARNING')
    error_count = sum(1 for r in results if r['status'] == 'ERROR')
    
    print(f"\n📊 汇总:✅ {ok_count} 正常 | ⚠️ {warning_count} 告警 | ❌ {error_count} 错误")
    
    return results

if __name__ == '__main__':
    health_check_all()

效果

5 分钟检查完 50 台服务器,自动生成报告

依赖安装

pip install paramiko

三、批量部署脚本

场景

需要同时更新 20 台服务器上的应用

传统做法

一台一台登录、拉代码、重启服务,花 2 小时

自动化方案

#!/usr/bin/env python3
"""
批量部署脚本
功能:同时在多台服务器上部署应用,支持回滚
"""
import paramiko
import time
from datetime import datetime

SERVERS = [
    {'host': '192.168.1.10', 'username': 'root', 'password': 'xxx'},
    {'host': '192.168.1.11', 'username': 'root', 'password': 'xxx'},
]

DEPLOY_CONFIG = {
    'app_dir': '/opt/myapp',
    'git_repo': 'git@github.com:myorg/myapp.git',
    'branch': 'main',
    'service_name': 'myapp'
}

def deploy_server(server, config):
    """在单台服务器上部署"""
    try:
        client = paramiko.SSHClient()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        client.connect(**server, timeout=10)
        
        commands = [
            f"cd {config['app_dir']}",
            "git fetch",
            f"git checkout {config['branch']}",
            "git pull",
            "pip install -r requirements.txt",
            f"systemctl restart {config['service_name']}",
            f"systemctl status {config['service_name']} --no-pager"
        ]
        
        print(f"\n🚀 开始部署 {server['host']}...")
        
        for cmd in commands:
            stdin, stdout, stderr = client.exec_command(cmd)
            exit_status = stdout.channel.recv_exit_status()
            
            if exit_status != 0:
                error_msg = stderr.read().decode()
                print(f"  ❌ 命令失败:{cmd}")
                print(f"  错误:{error_msg}")
                client.close()
                return False
            
            time.sleep(1)  # 避免命令执行过快
        
        print(f"  ✅ {server['host']} 部署成功")
        client.close()
        return True
        
    except Exception as e:
        print(f"  ❌ {server['host']} 部署失败:{str(e)}")
        return False

def rolling_deploy():
    """滚动部署(一次一台,避免服务中断)"""
    print("=" * 60)
    print(f"🚀 滚动部署开始 - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print("=" * 60)
    
    success_count = 0
    for i, server in enumerate(SERVERS, 1):
        print(f"\n[{i}/{len(SERVERS)}] 部署第 {i} 台服务器")
        if deploy_server(server, DEPLOY_CONFIG):
            success_count += 1
            print(f"  ⏳ 等待 30 秒观察服务状态...")
            time.sleep(30)  # 观察服务是否正常
        else:
            print(f"  ⚠️ 部署失败,暂停后续部署")
            break
    
    print(f"\n📊 部署完成:成功 {success_count}/{len(SERVERS)} 台")
    return success_count == len(SERVERS)

if __name__ == '__main__':
    success = rolling_deploy()
    exit(0 if success else 1)

效果

部署时间从 2 小时缩短到 15 分钟


四、数据库备份脚本

场景

每天需要备份 MySQL 数据库,并上传到云存储

自动化方案

#!/usr/bin/env python3
"""
数据库自动备份脚本
功能:备份 MySQL 数据库,压缩并上传到 OSS/S3
"""
import subprocess
import os
from datetime import datetime
import boto3  # AWS S3

# 配置
DB_CONFIG = {
    'host': 'localhost',
    'user': 'root',
    'password': 'your_password',
    'databases': ['db1', 'db2', 'db3']
}

BACKUP_DIR = '/backup/mysql'
S3_BUCKET = 'my-backup-bucket'
RETENTION_DAYS = 30  # 保留 30 天

def backup_database(db_name):
    """备份单个数据库"""
    timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
    filename = f"{db_name}_{timestamp}.sql.gz"
    filepath = os.path.join(BACKUP_DIR, filename)
    
    # 确保备份目录存在
    os.makedirs(BACKUP_DIR, exist_ok=True)
    
    # 执行备份命令
    cmd = f"mysqldump -h{DB_CONFIG['host']} -u{DB_CONFIG['user']} -p{DB_CONFIG['password']} {db_name} | gzip > {filepath}"
    
    try:
        subprocess.run(cmd, shell=True, check=True)
        print(f"  {db_name} 备份完成:{filename}")
        return filename
    except subprocess.CalledProcessError as e:
        print(f"  {db_name} 备份失败:{e}")
        return None

def upload_to_s3(filepath, bucket):
    """上传到 S3"""
    s3 = boto3.client('s3',
        aws_access_key_id='YOUR_KEY',
        aws_secret_access_key='YOUR_SECRET'
    )
    
    filename = os.path.basename(filepath)
    s3.upload_file(filepath, bucket, f"mysql/{filename}")
    print(f"☁️ 已上传到 S3: {bucket}/mysql/{filename}")

def cleanup_old_backups():
    """清理过期备份"""
    cutoff_date = datetime.now().timestamp() - (RETENTION_DAYS * 86400)
    
    for filename in os.listdir(BACKUP_DIR):
        filepath = os.path.join(BACKUP_DIR, filename)
        if os.path.getmtime(filepath) < cutoff_date:
            os.remove(filepath)
            print(f"🗑️ 已删除过期备份:{filename}")

def main():
    print("=" * 60)
    print(f"💾 数据库备份开始 - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print("=" * 60)
    
    for db_name in DB_CONFIG['databases']:
        filename = backup_database(db_name)
        if filename:
            filepath = os.path.join(BACKUP_DIR, filename)
            upload_to_s3(filepath, S3_BUCKET)
    
    cleanup_old_backups()
    
    print("\n 所有备份完成")

if __name__ == '__main__':
    main()

依赖安装

pip install boto3

配置 cron 定时任务

# 每天凌晨 2 点备份
0 2 * * * /usr/bin/python3 /opt/scripts/backup_mysql.py >> /var/log/backup.log 2>&1

五、SSL 证书到期提醒脚本

场景

管理多个域名,需要监控 SSL 证书到期时间

自动化方案

#!/usr/bin/env python3
"""
SSL 证书监控脚本
功能:检查证书到期时间,提前 30 天邮件提醒
"""
import ssl
import socket
import smtplib
from datetime import datetime
from email.mime.text import MIMEText
from email.header import Header

# 域名列表
DOMAINS = [
    'example.com',
    'api.example.com',
    'www.example.com'
]

# 邮件配置
EMAIL_CONFIG = {
    'smtp_server': 'smtp.qq.com',
    'smtp_port': 465,
    'from_addr': 'alert@example.com',
    'password': 'your_password',
    'to_addrs': ['admin@example.com']
}

def check_ssl_cert(domain, port=443):
    """检查 SSL 证书"""
    context = ssl.create_default_context()
    
    with socket.create_connection((domain, port)) as sock:
        with context.wrap_socket(sock, server_hostname=domain) as ssock:
            cert = ssock.getpeercert()
            not_after = datetime.strptime(cert['notAfter'], '%b %d %H:%M:%S %Y GMT')
            
            days_left = (not_after - datetime.utcnow()).days
            
            return {
                'domain': domain,
                'expire_date': not_after,
                'days_left': days_left,
                'status': 'OK' if days_left > 30 else 'WARNING'
            }

def send_alert_email(cert_info):
    """发送告警邮件"""
    subject = f"⚠️ SSL 证书即将到期 - {cert_info['domain']}"
    
    body = f"""
尊敬的运维团队:

域名 {cert_info['domain']} 的 SSL 证书即将到期!

📅 到期时间:{cert_info['expire_date'].strftime('%Y-%m-%d')}
⏰ 剩余天数:{cert_info['days_left']} 天

请尽快续期,避免服务中断!

---
自动化监控系统
{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
"""
    
    msg = MIMEText(body, 'plain', 'utf-8')
    msg['From'] = Header("SSL 监控", 'utf-8')
    msg['To'] = Header("运维团队", 'utf-8')
    msg['Subject'] = Header(subject, 'utf-8')
    
    with smtplib.SMTP_SSL(EMAIL_CONFIG['smtp_server'], EMAIL_CONFIG['smtp_port']) as server:
        server.login(EMAIL_CONFIG['from_addr'], EMAIL_CONFIG['password'])
        server.sendmail(
            EMAIL_CONFIG['from_addr'],
            EMAIL_CONFIG['to_addrs'],
            msg.as_string()
        )
    
    print(f"📧 已发送告警邮件到 {EMAIL_CONFIG['to_addrs']}")

def main():
    print("=" * 60)
    print(f"🔒 SSL 证书检查 - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print("=" * 60)
    
    for domain in DOMAINS:
        try:
            cert_info = check_ssl_cert(domain)
            
            status_icon = {'OK': '✅', 'WARNING': '⚠️'}
            print(f"\n{status_icon.get(cert_info['status'], '❓')} {domain}")
            print(f"  到期时间:{cert_info['expire_date'].strftime('%Y-%m-%d')}")
            print(f"  剩余天数:{cert_info['days_left']} 天")
            
            if cert_info['status'] == 'WARNING':
                send_alert_email(cert_info)
                
        except Exception as e:
            print(f"\n  ❌ {domain} 检查失败:{e}")
    
    print("\n✅ 检查完成")

if __name__ == '__main__':
    main()

效果

避免证书过期导致的服务中断


六、定时任务管理

脚本写好了,如何定时执行?

方案 1:Cron(简单任务)

# 编辑 crontab
crontab -e

# 每天早上 8 点检查服务器健康
0 8 * * * /usr/bin/python3 /opt/scripts/health_check.py >> /var/log/health.log 2>&1

# 每天凌晨 2 点备份数据库
0 2 * * * /usr/bin/python3 /opt/scripts/backup_mysql.py

方案 2:APScheduler(Python 内置)

from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetime

from my_scripts import health_check, backup_database

scheduler = BlockingScheduler()

# 每天早上 8 点执行健康检查
scheduler.add_job(health_check, 'cron', hour=8, minute=0)

# 每天凌晨 2 点备份数据库
scheduler.add_job(backup_database, 'cron', hour=2, minute=0)

# 每周一上午 9 点发送周报
scheduler.add_job(send_weekly_report, 'cron', day_of_week='mon', hour=9)

print("⏰ 调度器启动...")
scheduler.start()

安装:

pip install apscheduler

七、AI 时代的运维自动化

2026 年,AI 正在改变运维行业。但这 5 个脚本依然有价值,因为:

AI 做不了的

  • 定制化业务逻辑 — 每个公司环境不同,AI 无法完全理解
  • 敏感数据处理 — 安全考虑不能上传到 AI 平台
  • 实时响应 — 脚本本地执行,延迟更低,适合告警场景

AI 能帮你的

  • 用 Copilot 快速生成脚本框架
  • 让 AI 帮你 debug 和优化代码
  • 用自然语言描述需求,AI 生成初稿

我的建议

基础脚本自己写,复杂逻辑问 AI

这样既保证了安全性和可控性,又能借助 AI 提升效率。

比如这个健康检查脚本,你可以先让 AI 生成框架,然后根据自己的服务器环境修改 IP 列表和阈值。


八、最佳实践建议

1. 脚本管理

  • 统一存放在 /opt/scripts/ 目录
  • 使用 Git 版本控制
  • 添加详细的注释和文档

2. 日志记录

import logging

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    filename='/var/log/my_script.log'
)

logging.info("脚本执行成功")
logging.error("发生错误")

3. 错误处理

try:
    # 执行操作
    pass
except Exception as e:
    logging.error(f"操作失败:{e}")
    # 发送告警
    send_alert(f"脚本执行失败:{e}")
    exit(1)

4. 安全性

  • 敏感信息使用环境变量
  • 脚本权限设置为 700
  • 定期更新依赖包
import os

# 从环境变量读取密码
db_password = os.getenv('DB_PASSWORD')

最后

自动化是运维的核心竞争力之一。这 5 个脚本是我工作中最常用的,希望能帮你:

  • 节省时间 — 从重复劳动中解放
  • 减少错误 — 避免人为失误
  • 提升价值 — 把时间花在更有意义的事情上

好的运维不是救火英雄,而是让火灾永远不会发生的人。

自动化,就是预防火灾的最好方式。


💬 互动话题

你平时用什么工具做运维自动化?Python、Ansible 还是其他?

欢迎在评论区分享你的经验,或者告诉我你想看哪个脚本的详细教程!


🎁 福利

完整代码已开源到 GitHub,包含:

  • ✅ 5 个脚本的完整代码
  • ✅ 配置文件模板
  • ✅ 部署文档
  • ✅ 常见问题 FAQ

GitHub 地址: github.com/WGsummer/py…

觉得有用的话,欢迎 Star⭐ 支持!


如果这篇文章对你有帮助,麻烦点个赞👍,让更多运维兄弟看到!

你的每一个赞,都是我继续分享的动力!


相关资源:


本文首发于掘金,转载请联系作者