
1. 运维脚本这件事为什么值得用 AI 来写干了七八年运维我越来越觉得这个岗位的核心矛盾就一个要处理的破事越来越多但写脚本的时间越来越少。监控告警要写脚本、日志清理要写脚本、批量部署要写脚本、数据备份要写脚本甚至连查个磁盘占用都得临时拼一条命令。每次遇到新场景脑子里第一反应是“这个用 Python 写个脚本就能搞定”但真坐下来写的时候光是回忆subprocess怎么传参、argparse怎么定义可选参数、异常怎么捕获就能耗掉半小时。Codex 这类 AI 编程助手的出现对我来说最大的价值不是“帮我写代码”而是把写脚本这件事的门槛从“会写”降到了“会说”。你只要能把需求用自然语言描述清楚它就能给你一个能跑的骨架剩下的就是调试和微调。这个转变对运维来说意义很大因为运维的核心能力本来就不在编程语法上而在于对系统行为的理解和问题拆解能力。这篇文章我打算把自己这段时间用 Codex 写运维脚本的完整流程拆开讲一遍。从怎么描述需求、怎么设计 Prompt、怎么处理 AI 生成的代码里那些“看起来对但跑起来有问题”的坑到最终怎么把脚本落地到生产环境。适合两类人看一类是运维同行想用 AI 提效但不知道怎么下手另一类是有一定 Python 基础但没怎么写过运维脚本的开发想了解运维场景下脚本该怎么设计。提示本文提到的 Codex 泛指具备代码生成能力的 AI 编程助手不特指某一个产品。不同工具的交互方式有差异但核心方法论是通用的。2. 用 AI 写运维脚本的整体思路拆解2.1 为什么运维脚本特别适合交给 AI 生成运维脚本有一个非常好的特性模式化程度极高。你写过的脚本越多就越会发现大部分运维脚本的骨架是固定的——读取配置、连接目标、执行操作、处理结果、记录日志、异常退出。变的只是中间那几步的具体逻辑。这种高度模式化的任务恰好是 AI 最擅长的。它见过成千上万个类似的脚本知道logging模块该怎么初始化、知道try-except该捕获哪些异常、知道argparse的标准写法长什么样。你让它从零写一个“批量检查服务器磁盘使用率并在超过阈值时发告警”的脚本它给你的代码可能比很多初级运维手写的还规范。但这里有个前提你得把需求说清楚。AI 不会读心术你说“帮我写个监控脚本”它只能给你一个最通用的模板里面全是TODO。你说“帮我写一个脚本读取 servers.txt 里的 IP 列表通过 SSH 连上去执行 df -h解析出使用率超过 85% 的分区把结果写到 report.csv 里同时打印到终端”它给你的代码基本就能直接用了。2.2 人机分工的边界在哪里我用 Codex 写脚本这段时间慢慢摸清了一个分工原则AI 负责“怎么写”我负责“写什么”和“对不对”。具体来说AI 擅长的事情包括生成代码骨架和标准库调用、补全异常处理逻辑、写参数解析和帮助信息、生成日志格式、做数据格式转换。这些事情它有大量训练样本产出质量稳定。我必须自己把控的事情包括确认操作的安全性比如rm -rf的路径对不对、确认目标环境的特殊性比如某些命令在 CentOS 和 Ubuntu 上行为不同、确认权限和认证方式、确认脚本的幂等性。这些事情 AI 不知道你的环境长什么样它只能按通用情况处理你必须自己兜底。2.3 一个典型的协作流程我现在的流程基本固定下来了分四步需求拆解把要做的事情拆成“输入-处理-输出”三段明确每一步的细节。Prompt 编写把拆解结果写成结构化的描述附上环境信息Python 版本、操作系统、依赖库。代码审查拿到 AI 生成的代码后逐段检查关键操作特别是涉及文件删除、网络请求、权限变更的部分。本地验证先在测试环境跑一遍确认逻辑正确后再上生产。这四步里第一步和第三步是最耗时间的但也是最不能省的。我见过太多人直接复制 AI 生成的代码就往生产环境扔结果因为一个路径拼接错误把整个目录删了。这种事发生一次你对 AI 的信任就归零了。3. 核心细节解析与实操要点3.1 Prompt 怎么写才能让 AI 输出可用的代码写 Prompt 这件事我的经验是越具体越好但不要写成需求文档。AI 不是产品经理你给它写三千字的需求说明它反而抓不住重点。好的 Prompt 应该像你在跟一个刚入职的同事交代任务——说清楚背景、目标、约束条件剩下的让它自己发挥。我总结了一个运维脚本 Prompt 的模板结构背景我在什么环境下要解决什么问题 输入脚本接收什么参数或读取什么文件 处理具体要执行哪些操作按什么顺序 输出结果以什么形式呈现终端打印/写文件/发告警 约束Python 版本、依赖库限制、不能用的操作举个例子我要写一个“清理超过 30 天的日志文件”的脚本Prompt 会这样写背景Ubuntu 20.04 服务器Python 3.8日志目录 /var/log/myapp/ 下按日期存放日志文件格式为 app-YYYY-MM-DD.log。 输入脚本接收一个可选参数 --days默认 30表示保留最近多少天的日志。 处理扫描日志目录解析文件名中的日期删除超过指定天数的文件。 输出终端打印删除的文件列表和总数同时写入 /var/log/cleanup.log。 约束不要用 os.system 调用 shell 命令用 pathlib 和 datetime 处理。删除前先打印将要删除的文件加一个 --dry-run 参数支持只预览不删除。这个 Prompt 给出去Codex 生成的代码基本一次就能跑。关键点在于我把“不要用 os.system”和“加 dry-run”这两个约束写进去了这两个是运维脚本的安全底线。3.2 AI 生成的代码里最常见的三类问题用了这么久我发现 AI 生成的运维脚本代码问题基本集中在三个地方第一类是路径处理。AI 很喜欢用字符串拼接来构造路径比如dir / filename这在 Linux 上没问题但如果脚本要在 Windows 上跑就会出问题。更稳妥的做法是用pathlib.Path或者os.path.join。我现在的习惯是在 Prompt 里直接要求“用 pathlib 处理所有路径”。第二类是异常处理太宽泛。AI 经常写except Exception as e: print(e)这种把所有异常都吞掉了。运维脚本最怕这个因为出了问题你根本不知道是哪一步失败的。我会要求它针对具体操作捕获具体异常比如文件操作捕获FileNotFoundError和PermissionError网络操作捕获ConnectionError和TimeoutError。第三类是缺少幂等性考虑。比如一个“创建用户”的脚本AI 生成的代码直接useradd但如果用户已存在就会报错。运维脚本经常需要重复执行幂等性很重要。我会在 Prompt 里加一句“脚本需要支持重复执行已存在的资源不要报错”。3.3 参数解析和日志这两个模块必须自己把关argparse和logging这两个模块AI 生成的代码通常能用但细节上经常不符合运维习惯。参数解析方面AI 喜欢把所有参数都设成必填但运维脚本通常需要提供合理的默认值。比如一个备份脚本--source和--dest可以必填但--compress应该默认开启--retain-days应该默认 7 天。这些默认值的设定需要你根据实际使用场景来定AI 不知道你的习惯。日志方面AI 生成的代码经常只往终端打印但运维脚本必须同时写文件而且要有时间戳和日志级别。我通常会在 Prompt 里明确要求“用 logging 模块同时输出到终端和文件格式包含时间戳、级别、消息文件按天切割”。这样生成的代码基本就符合要求了。4. 实操过程与核心环节实现4.1 环境准备Python 环境配置的坑在开始写脚本之前环境得先弄好。这部分看起来简单但实际踩坑不少。Python 安装本身没什么好说的官网下载安装包或者用包管理器都行。关键是版本选择——我建议用 3.8 以上的版本因为很多新特性比如walrus运算符、f-string的增强在旧版本上用不了而 AI 生成的代码经常会用到这些特性。如果你服务器上只有 Python 3.6AI 生成的代码可能跑不起来。虚拟环境是必须的。我见过太多人直接在系统 Python 里pip install结果把系统自带的 Python 环境搞乱了最后连yum都用不了。用venv创建独立环境每个项目一个互不干扰python3 -m venv /opt/venv/ops-scripts source /opt/venv/ops-scripts/bin/activate pip install paramiko requests pyyaml依赖库的选择也有讲究。运维脚本常用的库就那么几个paramiko做 SSH 连接、requests做 HTTP 请求、pyyaml读配置文件、psutil获取系统信息。我建议在 Prompt 里明确告诉 AI“只用标准库和这几个库”避免它引入一些冷门的依赖增加部署复杂度。注意如果你在 Prompt 里没有限制依赖库AI 可能会引入fabric、ansible这类重型框架。对于简单的运维脚本来说这些框架太重了部署和维护成本都高。4.2 第一个实战脚本批量磁盘检查拿一个实际场景来走完整流程。需求是读取一个 IP 列表文件SSH 连到每台机器上执行df -h解析输出找出使用率超过阈值的分区汇总成报告。Prompt 编写写一个 Python 脚本用 paramiko 库实现 SSH 批量执行命令。 输入servers.txt 文件每行一个 IP格式为IP 用户名 密码用空格分隔。 处理读取文件依次 SSH 连接每台机器执行df -h解析输出中 Use% 列超过 85% 的行。 输出终端打印每台机器的异常分区同时写入 disk_report.csv格式为 IP,分区,使用率。 约束连接超时设为 10 秒单台机器失败不影响后续机器用 logging 记录所有操作。Codex 生成的代码大概长这样我做了简化import paramiko import csv import logging from concurrent.futures import ThreadPoolExecutor logging.basicConfig( levellogging.INFO, format%(asctime)s [%(levelname)s] %(message)s, handlers[ logging.FileHandler(disk_check.log), logging.StreamHandler() ] ) def check_disk(ip, user, password, threshold85): client paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: client.connect(ip, usernameuser, passwordpassword, timeout10) stdin, stdout, stderr client.exec_command(df -h) output stdout.read().decode() results [] for line in output.splitlines()[1:]: parts line.split() if len(parts) 5: use_pct parts[4].rstrip(%) if use_pct.isdigit() and int(use_pct) threshold: results.append((ip, parts[5], use_pct)) return results except Exception as e: logging.error(f{ip} 连接失败: {e}) return [] finally: client.close()这段代码基本可用但有几个地方我做了调整。第一AutoAddPolicy在生产环境有安全风险我改成了手动管理known_hosts。第二except Exception太宽泛我拆成了AuthenticationException、SSHException、socket.timeout分别处理。第三我加了ThreadPoolExecutor做并发因为串行执行 50 台机器太慢了。并发数的选择有个经验值SSH 连接是 IO 密集型操作并发数可以设高一些但不要超过目标机器的承受能力。我一般设 10 到 20 之间50 台机器大概 30 秒能跑完。如果设成 50 并发有些老机器的 SSH 服务可能扛不住。4.3 第二个实战脚本日志清理与归档这个场景更复杂一些涉及文件操作和日期计算。需求是清理指定目录下超过 N 天的日志文件清理前先压缩归档到备份目录。Prompt 编写写一个 Python 脚本清理日志目录并归档。 输入命令行参数 --log-dir日志目录、--backup-dir备份目录、--days保留天数默认 30、--dry-run只预览不执行。 处理扫描日志目录下所有 .log 文件解析文件名中的日期格式 YYYY-MM-DD找出超过保留天数的文件压缩为 tar.gz 放到备份目录然后删除原文件。 输出终端打印每个被处理的文件写入 cleanup.log。 约束用 pathlib 处理路径用 tarfile 做压缩删除前必须确认压缩文件存在且大小不为零支持 dry-run 模式。这个脚本的关键在于删除前的校验。AI 生成的代码通常会先压缩再删除但不会检查压缩是否成功。我加了一段逻辑压缩完成后检查目标文件是否存在、大小是否大于零确认无误后才删除原文件。这个检查看起来多余但实际救过我一次——有一次磁盘满了压缩文件写了一半就失败了如果没有这个检查原文件就被删了数据直接丢失。def archive_and_delete(file_path, backup_dir): date_str file_path.stem.split(-)[-3:] archive_name f{-.join(date_str)}.tar.gz archive_path backup_dir / archive_name with tarfile.open(archive_path, w:gz) as tar: tar.add(file_path, arcnamefile_path.name) if not archive_path.exists() or archive_path.stat().st_size 0: logging.error(f归档失败跳过删除: {file_path}) return False file_path.unlink() logging.info(f已归档并删除: {file_path}) return True4.4 第三个实战脚本配置文件批量下发这个场景涉及文件传输和内容替换。需求是把一份新的配置文件推送到多台机器上推送前先备份旧文件推送后重启对应服务。Prompt 编写写一个 Python 脚本用 paramiko 的 SFTP 批量下发配置文件。 输入servers.txtIP 列表、config.ini本地配置文件路径、remote_path远程目标路径、service_name需要重启的服务名。 处理对每台机器先备份远程的旧配置文件加 .bak 后缀然后上传新文件最后执行 systemctl restart 重启服务。 输出每台机器的操作结果打印到终端。 约束上传前检查本地文件是否存在备份时如果 .bak 已存在则加时间戳重启服务后检查服务状态。这个脚本的难点在于错误处理的分层。上传失败和重启失败是两种不同的错误处理方式也不一样。上传失败可以重试重启失败可能需要回滚。我在 Prompt 里没有写这么细但拿到代码后自己补了回滚逻辑如果重启失败就把备份文件恢复回去。def deploy_config(ip, user, password, local_config, remote_path, service): client paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: client.connect(ip, usernameuser, passwordpassword, timeout10) sftp client.open_sftp() backup_path f{remote_path}.bak.{int(time.time())} try: sftp.stat(remote_path) sftp.rename(remote_path, backup_path) logging.info(f{ip} 已备份旧配置到 {backup_path}) except FileNotFoundError: logging.warning(f{ip} 远程配置不存在跳过备份) sftp.put(local_config, remote_path) logging.info(f{ip} 配置上传成功) stdin, stdout, stderr client.exec_command(fsystemctl restart {service}) exit_code stdout.channel.recv_exit_status() if exit_code ! 0: error stderr.read().decode() logging.error(f{ip} 服务重启失败: {error}) sftp.rename(backup_path, remote_path) logging.info(f{ip} 已回滚配置) return False logging.info(f{ip} 服务重启成功) return True except Exception as e: logging.error(f{ip} 部署失败: {e}) return False finally: client.close()5. 常见问题与排查技巧实录5.1 AI 生成的代码跑不起来怎么办这是最常见的问题原因通常有三类。第一类是依赖库缺失。AI 生成的代码引用了某个库但你环境里没装。解决办法很简单看报错信息里的ModuleNotFoundError缺什么装什么。但要注意版本兼容性有些库的新版本改了 APIAI 生成的代码可能用的是旧版本的写法。我一般会在 Prompt 里指定库的版本比如“用 paramiko 2.11 版本”。第二类是 Python 版本不兼容。AI 可能用了 3.9 才支持的语法比如字典合并运算符|但你服务器上是 3.8。这种情况要么升级 Python要么让 AI 重写。我通常会在 Prompt 开头就写明 Python 版本避免这个问题。第三类是环境差异。AI 生成的代码在它的“认知”里是能跑的但你的环境有特殊性。比如它假设df -h的输出格式是标准的但某些定制化的系统输出格式不一样。这种情况只能自己调试打印出实际输出然后调整解析逻辑。5.2 脚本在生产环境跑出问题怎么快速定位运维脚本出问题最怕的是“静默失败”——脚本跑完了看起来没报错但实际什么都没做。我总结了一个排查顺序排查步骤检查内容常用命令1脚本是否真的执行了ps aux | grep script.py2日志文件有没有写入tail -f script.log3关键变量值是否正确在脚本里加logging.debug4网络连接是否正常telnet target port5权限是否足够ls -l检查文件权限6磁盘空间是否充足df -h我遇到最多的问题是权限。比如脚本用 root 跑没问题但放到 crontab 里用普通用户跑就失败了因为普通用户没有写日志目录的权限。这种问题看日志就能发现关键是日志要写清楚不能只写“操作失败”要写“写入 /var/log/cleanup.log 失败Permission denied”。5.3 怎么让 AI 生成的脚本更符合自己的编码习惯用久了你会发现AI 生成的代码虽然能用但风格跟你自己写的不一样。比如变量命名习惯、函数拆分粒度、注释风格。这些差异不影响功能但影响维护。我的做法是在 Prompt 里加一段“风格要求”比如代码风格要求变量名用 snake_case函数不超过 50 行每个函数加 docstring关键逻辑加行内注释用 f-string 做字符串格式化。这样生成的代码读起来就顺眼多了。另外我会把之前写好的脚本作为示例发给 AI让它参考我的风格。这个方法效果很好基本上两三次之后它生成的代码风格就跟我自己写的差不多了。5.4 哪些操作绝对不能让 AI 代劳有几类操作我坚持自己写不让 AI 生成第一类是涉及数据删除的。rm、DROP TABLE、truncate这类操作AI 生成的代码我必须逐行审查确认路径和条件判断没有问题。我甚至会要求 AI 在删除前加一个交互式确认或者强制要求--confirm参数。第二类是涉及权限变更的。chmod、chown、useradd这类操作一旦出错影响面很大。AI 生成的代码经常忽略“用户已存在”或“权限已经是目标值”的情况直接执行会报错。第三类是涉及网络配置的。修改防火墙规则、路由表、DNS 配置这类操作AI 不知道你的网络拓扑生成的代码可能把网络搞断。这类脚本我都是自己写AI 只用来做代码审查。提示一个实用的安全习惯——所有涉及危险操作的脚本第一次运行必须加--dry-run参数确认输出符合预期后再去掉。这个习惯帮我避免了好几次事故。5.5 脚本性能优化的几个实用技巧AI 生成的脚本通常能跑但性能不一定好。我总结几个优化点并发执行。批量操作一定要用并发ThreadPoolExecutor是最简单的方案。IO 密集型任务SSH、HTTP用线程池CPU 密集型任务用进程池。并发数根据目标机器的承受能力调整我一般从 10 开始试。连接复用。如果要对同一台机器执行多个操作不要每次都新建 SSH 连接。用paramiko的Transport复用连接或者用连接池。这个优化在批量操作时效果很明显50 台机器从 60 秒降到 15 秒。结果缓存。有些操作的结果在短时间内不会变比如获取主机名、操作系统版本。这些信息可以缓存到本地文件下次执行时直接读取避免重复请求。批量写入。如果脚本要写大量数据到文件或数据库不要一条一条写攒够一批再写。我用csv.writer的时候会先把所有结果收集到列表里最后一次性写入。6. 把 AI 写脚本这件事真正落地到日常运维6.1 建立自己的 Prompt 模板库用 AI 写脚本效率提升最明显的时候是你有一套自己的 Prompt 模板库。我现在按场景分类存了十几个模板批量命令执行、文件分发、日志清理、服务重启、数据备份、配置检查。每个模板里都包含了环境信息、约束条件、风格要求用的时候改一下具体需求就行。这个模板库是逐步积累的。每次写一个新脚本如果 Prompt 效果好就存下来如果效果不好就分析原因调整后重新存。几个月下来现在写一个新脚本从描述需求到拿到可用代码基本 10 分钟以内。6.2 代码审查不能省不管 AI 生成的代码看起来多靠谱审查这一步不能省。我的审查清单包括所有文件路径是否用了pathlib或os.path.join异常处理是否针对具体异常类型危险操作是否有确认机制日志是否写入了文件是否有硬编码的密码或密钥脚本是否支持重复执行这个清单我贴在显示器旁边每次审查的时候过一遍。大部分问题在前三项就能发现后面几项是兜底。6.3 从脚本到工具的演进用 AI 写脚本一段时间后你会发现有些脚本用得特别频繁这时候可以考虑把它做成工具。比如加个 Web 界面、做成命令行工具、集成到现有的运维平台里。我现在的做法是先用 AI 快速生成脚本原型验证逻辑没问题后再花时间把它工程化。工程化的内容包括加配置文件支持、加更完善的日志、加单元测试、打包成可执行文件。这个过程 AI 也能帮忙但核心的架构设计还是得自己来。6.4 一个真实的效率对比最后说个实际的数字。以前我写一个批量磁盘检查脚本从查文档到调试完成大概需要 2 小时。现在用 CodexPrompt 编写 10 分钟代码生成 1 分钟审查和调试 20 分钟总共半小时左右。效率提升大概 4 倍。但更重要的是心理门槛降低了。以前遇到一个“需要写脚本”的场景我会先评估一下值不值得花时间写。现在基本上只要觉得有用就直接让 AI 生成一个反正成本很低。这个转变带来的价值比单纯的时间节省更大。我在实际使用中最大的体会是AI 不会让你变成更好的程序员但它能让你把更多精力放在真正重要的事情上——理解系统行为、设计运维方案、解决实际问题。代码只是手段不是目的。