分类: 运维工具脚本

用 stat 归并 failed_when 判空与 changed_when 抑制无效报告的写法

在写 Ansible playbook 时,最常见的一个"报告污染"场景是这样的:先用 stat 判断某个文件或目录是否存在,存在就删掉再创建,不存在就直接创建。逻辑本身没错,但跑完之后你会发现 PLAY RECAP 里那一台机器明明什么都没改,却显示 changed=1;或者更糟,stat 的结果注册成变量后,后续 when 判空没写对,直接抛出 'dic

用 trap ERR 级联并区分命令退出的非零状态做分批失败补跑

批量任务脚本最怕的不是失败,而是失败得不明不白。一个循环里跑了 200 个对象,第 37 个因为网络抖动挂了,第 88 个因为鉴权过期挂了,第 150 个因为目标已存在挂了——三种原因,三种处理方式:第一种该重试,第二种该中断整个批次去换凭证,第三种根本不该算失败。可现实中大多数脚本只写了一句 || exit 1,于是所有失败糊成一团,运维只能翻日志人肉还原

用 docker compose config –quiet 做部署前的变量替换与格式预检

把 docker compose up -d 直接写进发布脚本,是很多团队踩过坑的做法。问题不在命令本身,而在于 Compose 文件的解析发生在容器真正启动之前:当 .env 缺变量、YAML 缩进错位、端口写成字符串、挂载路径引用了未定义变量时,报错往往夹杂在镜像拉取和容器创建日志里,排查成本高,而且失败可能发生在替换了部分容器之后,留下半新半旧的状态。

用 paramiko SFTP 配合 os.walk 实现远程目录与本地时间戳比对同步

很多团队的文件同步仍停留在 rsync 或 scp -r 一把梭的阶段,一旦目标机器只开放了 SFTP 且没有 shell 权限,或者需要在同步前做业务侧的白名单、过滤、二次处理,命令行工具就不够用了。更麻烦的是全量覆盖:源端有几千个文件,每次同步都重传一遍,带宽和时间都被浪费。本文给出一个纯 Python 的方案——用 paramiko 建立 SFTP 会

按 $request_uri 版本前缀配置 Nginx add_header 实现灰度流量标记

灰度发布时,后端服务往往需要知道「这个请求是不是灰度流量」,才能决定走新逻辑还是老逻辑。最省事的入口标记点就在 Nginx:在反向代理层解析 $request_uri,按版本前缀(例如 /v2/、/beta/)打上响应头,让下游网关、应用、甚至前端调试面板都能看到流量归属。本文解决三个具体问题:怎么用 map 稳定地从前缀推导标记、add_header 在哪

awk 结合 NR 从 journalctl 导出日志中截取指定时间窗口

把线上故障时间点定位到分钟级之后,多数人第一反应是翻 journalctl -u,但真正到复盘、提交工单、给外部同事看的时候,往往需要把「某个服务在 14:05 到 14:20 之间的全部日志」导出成一个文件。问题在于:日志导出后可能存成 app.log、app.log.1,也可能是别人从别的机器 journalctl --since ... --until

用 while read 配合 IFS= 读取含空格路径清单换行安全的写法

批量处理文件清单是运维脚本的日常:备份目录列表、待清理日志清单、批量重命名映射表。很多人第一次踩坑都长一个样——清单里明明有 a b/c.log 这种带空格的路径,脚本跑完发现只处理了 a,后半截 b/c.log 被当成了另一个变量或者直接丢掉。更糟的是循环体里一执行 ssh、ffmpeg、read 之类会吃掉标准输入的命令,循环莫名其妙只跑了第一行就结束了