1. 引言

运维工程师每天都在和重复性工作打交道:日志清理、服务巡检、批量部署、故障排查……这些工作往往需要编写大量脚本。而 Codex 作为 OpenAI 推出的 AI 编程助手,正在改变我们编写运维脚本的方式。

本文将带你从零开始,用 Codex 实战编写运维脚本,涵盖环境准备、需求描述、脚本生成、调试优化到落地使用的完整流程。

2. Codex 是什么

2.1 Codex 简介

Codex 是 OpenAI 推出的 AI 编程助手,能够理解自然语言指令并生成、修改、调试代码。它基于大语言模型,支持多种编程语言,尤其擅长 Python、Shell 等运维常用语言。

2.2 Codex 与传统写脚本方式的对比

维度传统方式Codex 辅助
编写速度慢,需逐行手写快,自然语言描述即可生成
调试成本高,需人工排查低,可让 AI 协助定位问题
知识储备依赖个人经验内置大量最佳实践
可维护性取决于个人编码习惯可要求生成规范注释和结构

3. 环境准备

3.1 安装与配置 Codex

首先需要安装 Codex 命令行工具,并配置 API Key:

# 安装 Codex CLI
npm install -g @openai/codex

# 配置 API Key
export OPENAI_API_KEY="your-api-key"

3.2 准备测试环境

建议在虚拟机或容器中准备一个测试环境,避免影响生产系统:

# 创建测试容器
docker run -it --name ops-test ubuntu:22.04 bash

4. 用 Codex 编写第一个运维脚本

4.1 需求描述

编写运维脚本的第一步是清晰描述需求。例如,我们需要一个日志清理脚本:

请帮我写一个 Python 脚本,用于清理 /var/log 目录下超过 7 天的 .log 文件,要求:

  1. 支持指定目录和保留天数作为参数
  2. 删除前打印将要删除的文件列表
  3. 支持 --dry-run 参数,只预览不删除

4.2 Codex 生成脚本

将上述需求输入 Codex,它会生成类似下面的脚本:

#!/usr/bin/env python3
"""日志清理脚本:删除指定目录下超过保留天数的日志文件。"""

import argparse
import os
import time
from pathlib import Path


def parse_args():
    """解析命令行参数。"""
    parser = argparse.ArgumentParser(description="清理过期日志文件")
    parser.add_argument("--dir", default="/var/log", help="要清理的目录")
    parser.add_argument("--days", type=int, default=7, help="保留天数")
    parser.add_argument("--dry-run", action="store_true", help="只预览不删除")
    return parser.parse_args()


def find_expired_files(directory: str, days: int):
    """找出超过保留天数的 .log 文件。"""
    cutoff = time.time() - days * 86400
    expired = []
    for path in Path(directory).rglob("*.log"):
        if path.is_file() and path.stat().st_mtime < cutoff:
            expired.append(path)
    return expired


def main():
    args = parse_args()
    expired_files = find_expired_files(args.dir, args.days)

    if not expired_files:
        print("没有找到过期文件。")
        return

    print(f"发现 {len(expired_files)} 个过期文件:")
    for f in expired_files:
        print(f"  {f}")

    if args.dry_run:
        print("[dry-run] 以上文件将被删除,本次未实际删除。")
        return

    for f in expired_files:
        f.unlink()
    print(f"已删除 {len(expired_files)} 个文件。")


if __name__ == "__main__":
    main()

4.3 验证脚本

# 先以 dry-run 模式运行
python3 clean_logs.py --dir /tmp/test-logs --days 7 --dry-run

# 确认无误后正式执行
python3 clean_logs.py --dir /tmp/test-logs --days 7

5. 用 Codex 编写 Shell 运维脚本

5.1 服务健康巡检脚本

运维中经常需要批量检查服务状态,用 Codex 生成一个 Shell 脚本:

写一个 Shell 脚本,检查一组服务的运行状态,输出每个服务的 PID、内存占用和端口监听情况,异常时用红色输出警告。

#!/bin/bash
# 服务健康巡检脚本

SERVICES=("nginx" "mysql" "redis")

for svc in "${SERVICES[@]}"; do
    echo "=== 检查服务: $svc ==="

    # 检查进程
    pid=$(pgrep -x "$svc" | head -1)
    if [ -z "$pid" ]; then
        echo -e "\033[31m[警告] $svc 未运行!\033[0m"
        continue
    fi
    echo "PID: $pid"

    # 内存占用
    mem=$(ps -o rss= -p "$pid" | awk '{printf "%.1fMB", $1/1024}')
    echo "内存: $mem"

    # 端口监听
    port=$(ss -tlnp 2>/dev/null | grep "$pid" | awk '{print $4}' | cut -d: -f2 | head -1)
    echo "端口: ${port:-未监听}"
done

5.2 批量部署脚本

再让 Codex 生成一个批量部署脚本,用于在多台服务器上同步代码并重启服务:

写一个脚本,从配置文件读取服务器列表,通过 SSH 批量执行部署命令(拉取代码、重启服务),并记录每台机器的执行结果。

#!/bin/bash
# 批量部署脚本
# 用法: ./deploy.sh servers.txt

SERVERS_FILE="${1:-servers.txt}"
DEPLOY_CMD="cd /app && git pull && systemctl restart myapp"

if [ ! -f "$SERVERS_FILE" ]; then
    echo "错误: 服务器列表文件 $SERVERS_FILE 不存在"
    exit 1
fi

while IFS= read -r server; do
    [ -z "$server" ] && continue
    echo ">>> 部署到 $server ..."
    if ssh -o ConnectTimeout=5 "$server" "$DEPLOY_CMD" 2>&1; then
        echo ">>> $server 部署成功"
    else
        echo ">>> $server 部署失败" | tee -a deploy_errors.log
    fi
done < "$SERVERS_FILE"

echo "部署完成,失败记录见 deploy_errors.log"

6. 用 Codex 调试与优化脚本

6.1 让 Codex 帮忙排查问题

脚本运行报错时,直接把错误信息贴给 Codex:

我的脚本报错:PermissionError: [Errno 13] Permission denied: '/var/log/nginx/access.log',请帮我分析原因并给出修复方案。

Codex 会分析出权限问题,并建议使用 sudo 运行或调整文件权限。

6.2 优化脚本性能

请优化这个脚本,它处理 10 万行日志时太慢了。当前用 for 循环逐行读取,请改用更高效的方式。

Codex 会建议使用 pandas 或 awk 等更高效的工具,并给出优化后的代码。

6.3 增加健壮性

请给脚本增加异常处理、日志记录和重试机制,确保在部分失败时能继续执行。

7. 运维脚本的最佳实践

7.1 给 Codex 的提示词技巧

  • 明确输入输出:说清楚脚本的输入参数和期望输出
  • 给出约束条件:如"兼容 Python 3.8+"、“不要使用外部依赖”
  • 要求注释和文档:让 Codex 生成带注释和 README 的完整脚本
  • 分步生成:复杂脚本先让 Codex 生成框架,再逐步补充细节

7.2 脚本安全注意事项

  • 涉及删除、覆盖操作时,务必先 --dry-run 预览
  • 生产环境脚本要加权限校验和操作确认
  • 敏感信息(密码、密钥)不要硬编码在脚本中
  • 重要操作前自动备份

7.3 脚本的可维护性

  • 统一使用 argparse 或 getopts 解析参数
  • 输出格式统一,便于日志采集
  • 添加 set -euo pipefail(Shell)或异常处理(Python)
  • 为脚本编写 README 和使用示例

8. 实战案例:完整监控告警脚本

8.1 需求描述

综合运用以上技巧,让 Codex 生成一个完整的磁盘监控告警脚本:

写一个 Python 脚本,监控所有挂载点的磁盘使用率,超过 80% 时输出告警,超过 90% 时发送邮件通知,支持通过配置文件设置阈值和收件人。

8.2 Codex 生成结果

#!/usr/bin/env python3
"""磁盘使用率监控告警脚本。"""

import configparser
import shutil
import smtplib
import sys
from email.mime.text import MIMEText

CONFIG_FILE = "disk_monitor.conf"


def load_config():
    """加载配置文件。"""
    config = configparser.ConfigParser()
    config.read(CONFIG_FILE)
    return {
        "warn_threshold": config.getint("monitor", "warn_threshold", fallback=80),
        "alert_threshold": config.getint("monitor", "alert_threshold", fallback=90),
        "smtp_server": config.get("alert", "smtp_server", fallback=""),
        "smtp_port": config.getint("alert", "smtp_port", fallback=25),
        "sender": config.get("alert", "sender", fallback=""),
        "recipients": config.get("alert", "recipients", fallback="").split(","),
    }


def check_disk_usage():
    """检查所有挂载点的磁盘使用率。"""
    warnings = []
    alerts = []
    for partition in shutil.disk_usage("/"):
        pass  # 实际实现需遍历挂载点

    # 简化示例:检查根分区
    usage = shutil.disk_usage("/")
    percent = usage.used / usage.total * 100
    mount = "/"

    if percent >= cfg["alert_threshold"]:
        alerts.append((mount, percent))
    elif percent >= cfg["warn_threshold"]:
        warnings.append((mount, percent))

    return warnings, alerts


def send_alert(subject, body):
    """发送告警邮件。"""
    msg = MIMEText(body, "plain", "utf-8")
    msg["Subject"] = subject
    msg["From"] = cfg["sender"]
    msg["To"] = ", ".join(cfg["recipients"])

    with smtplib.SMTP(cfg["smtp_server"], cfg["smtp_port"]) as server:
        server.sendmail(cfg["sender"], cfg["recipients"], msg.as_string())


def main():
    warnings, alerts = check_disk_usage()

    for mount, percent in warnings:
        print(f"[警告] {mount} 使用率 {percent:.1f}%")

    for mount, percent in alerts:
        msg = f"[严重] {mount} 使用率 {percent:.1f}%,请及时处理!"
        print(msg)
        send_alert("磁盘告警", msg)


if __name__ == "__main__":
    cfg = load_config()
    main()

8.3 配置与部署

# disk_monitor.conf
[monitor]
warn_threshold = 80
alert_threshold = 90

[alert]
smtp_server = smtp.example.com
smtp_port = 25
sender = monitor@example.com
recipients = ops@example.com,admin@example.com

配合 crontab 定时执行:

# 每 10 分钟执行一次
*/10 * * * * /usr/bin/python3 /opt/scripts/disk_monitor.py

9. 总结与展望

9.1 本文总结

通过本文的实战,我们掌握了用 Codex 编写运维脚本的完整流程:

  1. 清晰描述需求:把运维任务转化为明确的自然语言指令
  2. 生成脚本:让 Codex 生成初版代码
  3. 验证与调试:在测试环境验证,用 Codex 协助排查问题
  4. 优化与加固:让 Codex 优化性能、增加健壮性
  5. 落地部署:配置定时任务,纳入日常运维体系

9.2 Codex 在运维中的更多应用

  • 日志分析脚本
  • 配置批量修改工具
  • 故障自动恢复脚本
  • 容量规划与报表生成
  • 云资源巡检与成本优化

9.3 给运维工程师的建议

Codex 不是要取代运维工程师,而是成为你的得力助手。把重复性、模式化的脚本编写交给 AI,把精力集中在架构设计、故障处理和业务理解上,这才是 AI 时代运维工程师的正确姿势。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐