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 会建议使用 pandasawk 等更高效的工具,并给出优化后的代码。

6.3 增加健壮性

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

7. 运维脚本的最佳实践

7.1 给 Codex 的提示词技巧

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

7.2 脚本安全注意事项

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

7.3 脚本的可维护性

  • 统一使用 argparsegetopts 解析参数
  • 输出格式统一,便于日志采集
  • 添加 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

葡萄城是专业的软件开发技术和低代码平台提供商,聚焦软件开发技术,以“赋能开发者”为使命,致力于通过表格控件、低代码和BI等各类软件开发工具和服务,一站式满足开发者需求,帮助企业提升开发效率并创新开发模式。

更多推荐