patch 是什么
patch 把 diff 生成的补丁文件应用到目标文件或目录上,是发布修复、同步配置的标准手段。它的关键参数是 -p(决定路径里丢弃几层前缀)、--dry-run(只演练不落盘)与 -R(反向回滚)。因为应用失败会留下未生效片段,生产改动前先演练这一步不能省。
基本信息
| 适用平台 | Linux/Unix(GNU patch;BSD 版选项略有差异) |
|---|---|
| 命令语法 | patch [-pN] [--dry-run] < 变更.patch |
| 常用选项 | -pN 丢弃 N 层目录前缀 -b 应用前给原文件留 .orig 备份 --dry-run 只演练 -R 反向回滚 -F0 禁用模糊匹配 |
| 配套工具 | diff -u 生成单文件补丁,diff -ruN 生成整树补丁 |
| 退出码 | 0 成功、1 有失败片段(会留下 .rej)、2 严重错误 |
典型使用场景
- 应用上游修复:把供应商给的补丁打进源码或配置
- 同步配置到多台机器:先生成补丁再分发应用
- 回滚一次改动:用同一个补丁加 -R 反向应用
- 变更评审:先用 --dry-run 确认能干净应用,再正式执行
- 修复历史包袱:对已改过的文件打补丁,处理冲突片段
常用流程
常用流程
head -n 5 fix.patch # 先看补丁头的路径前缀
patch -p1 --dry-run < fix.patch # 只在内存里演练,不落盘
patch -p1 -b < fix.patch # 正式应用,同时留 .orig 备份
patch -R -p1 < fix.patch # 需要时反向回滚
patch -p0 < app.conf.patch # 无目录前缀的本地补丁
patch -p1 -F0 < strict.patch # 关闭模糊匹配,要求上下文完全一致补丁头与 -p 的对应
| 补丁头路径形态 | -p 取值 | 场景 |
|---|---|---|
| a/app.conf 与 b/app.conf | -p1 | git 风格补丁,最常见 |
| app.conf | -p0 | 本地直接对文件生成、无前缀 |
| conf.old/app.conf | -p1 | 目录对目录但无 a/ b/ 前缀 |
| 绝对路径 /home/u/app.conf | 按组件数计算 | 不推荐,路径不可移植 |
应用失败时会留下 .rej 未应用片段与 .orig 备份:必须处理完 .rej 的内容(或明确放弃并回滚)再清理它们,别把「有 .rej 但命令没报错」当成成功。用 -R 回滚的前提是目标文件在打补丁之后没有再被修改。
--dry-run 与正式执行要使用完全相同的 -p 与其他参数,否则演练的结论不成立;批量给多台机器打补丁时,先在一台上跑通并把命令固化下来,再分发执行。
补丁不具备幂等性:对同一个文件重复应用会因为上下文已变而失败。多机分发前先确认目标文件与生成补丁时的基线一致(比对校验和或版本号),并在脚本里判断「是否已经打过」,否则会出现一半机器成功、一半要求人工处理的局面。