1. 引言

在日常运维工作中,脚本编写往往占据大量时间:日志分析、批量部署、故障排查、数据备份……这些任务重复且耗时。随着 AI 编程助手的发展,Codex 等工具正在改变运维工程师的工作方式——从「手写每一行代码」到「用自然语言描述需求,让 AI 生成脚本」。

本文将带你从零开始,掌握使用 Codex 编写运维脚本的完整流程,包括环境准备、提示词技巧、实战案例以及常见坑点,帮助你真正把 AI 应用到日常运维工作中。

2. Codex 简介与核心能力

2.1 什么是 Codex

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

2.2 核心能力

  • 代码生成:根据自然语言描述生成完整脚本
  • 代码解释:分析现有脚本的逻辑与作用
  • 代码优化:重构冗余代码,提升执行效率
  • 错误修复:定位并修复脚本中的 Bug
  • 多语言支持:Python、Bash、PowerShell、Go 等

2.3 适用场景

  • 日志分析与统计
  • 批量文件处理与备份
  • 系统监控与告警
  • 自动化部署与配置
  • 故障排查与诊断

3. 环境准备与接入方式

3.1 接入方式对比

接入方式适用场景优点缺点
官方 Web 界面日常交互式提问无需配置,开箱即用无法集成到自动化流程
API 调用集成到自研工具可编程控制,支持批量需要 API Key,有费用
命令行工具本地开发环境与终端工作流无缝衔接需要安装配置
IDE 插件开发调试阶段上下文感知,实时补全依赖 IDE 环境

3.2 环境准备清单

  • 注册 OpenAI 账号并获取 API Key
  • 安装 Python 3.8+ 环境
  • 安装 Codex CLI 工具(如适用)
  • 配置网络代理(如需要)

3.3 快速验证

# 安装 Codex CLI(示例)
pip install codex-cli

# 验证是否安装成功
codex --version

4. 编写高效提示词的核心技巧

4.1 提示词五要素

一个高质量的运维脚本提示词,通常包含以下五个要素:

  1. 角色设定:明确 Codex 扮演的角色
  2. 任务描述:清晰说明要完成的任务
  3. 输入输出:指定输入数据格式和期望输出
  4. 约束条件:说明运行环境、依赖、性能要求
  5. 示例参考:提供输入输出示例帮助理解

4.2 提示词模板

你是一位资深运维工程师,请帮我编写一个 Python 脚本。

任务:分析 Nginx 访问日志,统计每个 IP 的访问次数,并输出 Top 10。

输入:/var/log/nginx/access.log,每行格式为:
$remote_addr - - [$time_local] "$request" $status $body_bytes_sent

输出:按访问次数降序排列的 IP 列表,格式为:
IP地址 访问次数

约束:
- 使用 Python 3,仅依赖标准库
- 日志文件可能很大,需考虑内存优化
- 输出结果保存到 result.txt

4.3 常见误区

  • 描述过于笼统:只说「写个监控脚本」,没有明确监控对象和告警方式
  • 忽略边界情况:未说明文件不存在、格式异常等情况的处理
  • 缺少验证标准:没有定义「脚本正确」的验收标准

5. 实战案例一:日志分析脚本

5.1 需求描述

编写一个 Python 脚本,分析 Web 服务器访问日志,统计各状态码(200、404、500 等)的出现次数,并输出占比最高的前 5 个状态码。

5.2 提示词示例

请编写一个 Python 脚本 analyze_log.py,功能如下:

1. 读取指定日志文件(通过命令行参数传入路径)
2. 使用正则表达式提取每行中的 HTTP 状态码
3. 统计各状态码出现次数
4. 输出占比最高的前 5 个状态码及其占比(保留两位小数)
5. 如果文件不存在,打印友好错误信息并退出

示例日志行:
192.168.1.1 - - [05/Sep/2026:10:30:00 +0800] "GET /index.html HTTP/1.1" 200 1024

5.3 生成结果示例

#!/usr/bin/env python3
"""分析 Web 访问日志中的 HTTP 状态码分布。"""

import re
import sys
from collections import Counter


def analyze_log(filepath: str) -> None:
    """读取日志文件并统计状态码分布。"""
    pattern = re.compile(r'"\w+\s+\S+\s+HTTP/\d\.\d"\s+(\d{3})')
    status_counter = Counter()

    try:
        with open(filepath, "r", encoding="utf-8") as f:
            for line in f:
                match = pattern.search(line)
                if match:
                    status_counter[match.group(1)] += 1
    except FileNotFoundError:
        print(f"错误:文件 {filepath} 不存在", file=sys.stderr)
        sys.exit(1)

    total = sum(status_counter.values())
    if total == 0:
        print("未找到有效的状态码记录")
        return

    print(f"{'状态码':<8}{'次数':<8}{'占比':<8}")
    print("-" * 24)
    for status, count in status_counter.most_common(5):
        percent = count / total * 100
        print(f"{status:<8}{count:<8}{percent:.2f}%")


if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("用法:python analyze_log.py <日志文件路径>")
        sys.exit(1)
    analyze_log(sys.argv[1])

5.4 验证与优化

  • 用真实日志样本测试脚本输出
  • 检查边界情况:空文件、超大文件、异常格式
  • 根据实际需求调整 Top N 数量或输出格式

6. 实战案例二:批量服务器状态检查

6.1 需求描述

编写一个 Bash 脚本,批量检查多台服务器的 CPU、内存、磁盘使用率,并将结果汇总输出。

6.2 提示词示例

请编写一个 Bash 脚本 check_servers.sh,功能如下:

1. 从 servers.txt 文件中读取服务器列表(每行一个 IP 或主机名)
2. 通过 SSH 连接每台服务器,执行以下命令:
   - CPU 使用率:top -bn1 | grep "Cpu(s)"
   - 内存使用率:free -m
   - 磁盘使用率:df -h /
3. 将每台服务器的检查结果汇总,以表格形式输出
4. 支持通过 -u 参数指定 SSH 用户名
5. 某台服务器连接失败时,跳过并记录错误,不中断整个脚本

6.3 生成结果示例

#!/bin/bash
# 批量检查服务器资源使用情况

USERNAME="root"
SERVERS_FILE="servers.txt"

# 解析参数
while getopts "u:" opt; do
    case $opt in
        u) USERNAME="$OPTARG" ;;
        *) echo "用法:$0 [-u 用户名]"; exit 1 ;;
    esac
done

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

echo "开始检查服务器状态..."
echo "=========================================="

while IFS= read -r server; do
    [ -z "$server" ] && continue
    echo ">>> 正在检查 $server ..."

    if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no "$USERNAME@$server" \
        "echo '--- CPU ---'; top -bn1 | grep 'Cpu(s)'; \
         echo '--- 内存 ---'; free -m | grep Mem; \
         echo '--- 磁盘 ---'; df -h / | tail -1" 2>/dev/null; then
        echo ">>> $server 检查完成"
    else
        echo ">>> $server 连接失败,已跳过" >&2
    fi
    echo "------------------------------------------"
done < "$SERVERS_FILE"

echo "全部检查完成。"

6.4 安全注意事项

  • 建议使用 SSH 密钥认证而非密码
  • 限制脚本执行权限,避免敏感信息泄露
  • 生产环境建议增加超时与重试机制

7. 实战案例三:自动化备份脚本

7.1 需求描述

编写一个 Python 脚本,将指定目录打包压缩,并上传到远程备份服务器,同时保留最近 7 天的备份。

7.2 提示词示例

请编写一个 Python 脚本 backup.py,功能如下:

1. 接收两个参数:源目录路径、备份服务器地址
2. 将源目录打包为 tar.gz 格式,文件名包含日期(如 backup_20260905.tar.gz)
3. 通过 scp 上传到备份服务器的 /backup 目录
4. 上传成功后,删除本地超过 7 天的旧备份文件
5. 使用 logging 模块记录执行日志,包括开始、成功、失败信息
6. 任何步骤失败时,记录错误并以非零状态码退出

7.3 生成结果示例

#!/usr/bin/env python3
"""自动化目录备份脚本:打包、上传、清理旧备份。"""

import argparse
import logging
import os
import subprocess
import sys
from datetime import datetime, timedelta

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)
logger = logging.getLogger(__name__)

BACKUP_DIR = "/backup"
RETENTION_DAYS = 7


def create_archive(source_dir: str) -> str:
    """将源目录打包为 tar.gz,返回文件名。"""
    date_str = datetime.now().strftime("%Y%m%d")
    archive_name = f"backup_{date_str}.tar.gz"

    logger.info("开始打包 %s -> %s", source_dir, archive_name)
    result = subprocess.run(
        ["tar", "-czf", archive_name, "-C", os.path.dirname(source_dir),
         os.path.basename(source_dir)],
        capture_output=True,
        text=True,
    )
    if result.returncode != 0:
        logger.error("打包失败:%s", result.stderr)
        sys.exit(1)
    logger.info("打包完成:%s", archive_name)
    return archive_name


def upload_archive(archive_name: str, remote_host: str) -> None:
    """通过 scp 上传备份文件到远程服务器。"""
    logger.info("上传 %s 到 %s:%s", archive_name, remote_host, BACKUP_DIR)
    result = subprocess.run(
        ["scp", archive_name, f"{remote_host}:{BACKUP_DIR}/"],
        capture_output=True,
        text=True,
    )
    if result.returncode != 0:
        logger.error("上传失败:%s", result.stderr)
        sys.exit(1)
    logger.info("上传成功")


def cleanup_old_backups() -> None:
    """删除本地超过保留天数的旧备份文件。"""
    cutoff = datetime.now() - timedelta(days=RETENTION_DAYS)
    for filename in os.listdir("."):
        if not filename.startswith("backup_") or not filename.endswith(".tar.gz"):
            continue
        filepath = os.path.join(".", filename)
        mtime = datetime.fromtimestamp(os.path.getmtime(filepath))
        if mtime < cutoff:
            os.remove(filepath)
            logger.info("已删除旧备份:%s", filename)


def main() -> None:
    parser = argparse.ArgumentParser(description="自动化备份脚本")
    parser.add_argument("source_dir", help="要备份的源目录")
    parser.add_argument("remote_host", help="备份服务器地址")
    args = parser.parse_args()

    if not os.path.isdir(args.source_dir):
        logger.error("源目录不存在:%s", args.source_dir)
        sys.exit(1)

    archive_name = create_archive(args.source_dir)
    upload_archive(archive_name, args.remote_host)
    cleanup_old_backups()
    logger.info("备份流程全部完成")


if __name__ == "__main__":
    main()

7.4 扩展建议

  • 增加加密功能,保护敏感数据
  • 接入定时任务(cron),实现全自动备份
  • 增加备份完整性校验(MD5/SHA256)

8. 常见问题与调试技巧

8.1 生成脚本不满足需求怎么办

  • 补充细节:提供更具体的输入输出示例
  • 分步提问:将复杂任务拆解为多个小任务逐步生成
  • 要求重构:明确要求「用更简洁的方式重写」「增加错误处理」

8.2 脚本运行报错如何排查

  • 将报错信息完整复制给 Codex,要求解释原因
  • 提供脚本上下文,要求定位问题行
  • 要求生成测试用例验证关键逻辑

8.3 安全与合规注意事项

  • 不要在提示词中包含敏感信息(密码、密钥、Token)
  • 生成脚本涉及生产环境操作时,先在测试环境验证
  • 对 AI 生成的脚本进行人工审查后再上线

9. 总结与进阶建议

9.1 核心要点回顾

  • 明确需求是高效使用 Codex 的前提
  • 提示词越具体,生成结果越符合预期
  • AI 生成脚本仍需人工验证与优化
  • 将常用提示词沉淀为模板,提升复用效率

9.2 进阶学习方向

  • 学习 Codex API 集成,构建自动化运维工具链
  • 结合 CI/CD 流程,实现脚本自动生成与测试
  • 探索多 Agent 协作,处理更复杂的运维场景

9.3 实践建议

从今天开始,选择一个你日常最耗时的运维任务,尝试用 Codex 生成第一版脚本。在实践中积累提示词经验,逐步建立自己的「AI 运维脚本库」,让重复性工作真正自动化起来。

Logo

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

更多推荐