歡迎光臨
每天分享高質量文章

diff 與 patch 的使用 | Linux 中國

在 Linux 的日常使用中,我們經常需要修改一些配置檔案,然而在軟體升級以後,經常會面臨配置更新後與原配置部分不相容的問題(當然我們更多的可能是來製作軟體升級的補丁)
— Locez


致謝
轉載自 | http://locez.com/linux/diff-and-patch/
 作者 | Locez

摘要

在 Linux 的日常使用中,我們經常需要修改一些配置檔案,然而在軟體升級以後,經常會面臨配置更新後與原配置部分不相容的問題(當然我們更多的可能是來製作軟體升級的補丁)。在這種情況下我們通常有兩種選擇:

◈ 對比現有配置,手動在新配置檔案中改動
◈ 利用 sedawk 等工具配合改動
◈ 採用 diff 與 patch 製作增量補丁的方式改動

本文主要透過一個升級awesome 配置的例子,對第三種方法進行介紹和講解。

diff 介紹

diff 是一個檔案比較工具,可以逐行比較兩個檔案的不同,其中它有三種輸出方式,分別是 normal, context 以及 unified。區別如下:

◈ normal 方式為預設輸出方式,不需要加任何引數
◈ context 相較於 normal 樣式的簡單輸出,contetx 樣式會輸出修改過部分的背景關係,預設是前後 3 行。使用引數 -c
◈ unified 合併背景關係樣式則為新的背景關係輸出樣式,同樣為前後 3 行,只不過把背景關係合併了顯示了。使用引數 -u

:本文主要介紹 unified 樣式

其他常用引數:

◈ -r 遞迴處理目錄
◈ -N 將缺失的檔案當作空白檔案處理

diff 語法與檔案格式

  1. diff [options] old new

先來看一個簡單的例子:

  1. $ cat test1

  2. linux

  3. linux

  4. linux

  5. linux

  1. $ cat test2

  2. locez

  3. linux

  4. locez

  5. linux

此時輸入 diff -urN test1 test2 會輸出以下資訊:

  1. --- test1   2018-05-12 18:39:41.508375114 +0800

  2. +++ test2   2018-05-12 18:41:00.124031736 +0800

  3. @@ -1,4 +1,4 @@

  4. +locez

  5. linux

  6. -linux

  7. -linux

  8. +locez

  9. linux

先看前面 2 行,這兩行為檔案的基本資訊,--- 開頭為改變前的檔案,+++ 開頭為更新後的檔案。

  1. --- test1   2018-05-12 18:39:41.508375114 +0800

  2. +++ test2   2018-05-12 18:41:00.124031736 +0800

第三行為背景關係描述塊,其中 -1,4 為舊檔案的 4 行背景關係,+1,4 為新檔案的:

  1. @@ -1,4 +1,4 @@

而具體到塊裡面的內容,前面有 - 號的則為刪除,有 + 號為新增,不帶符號則未做改變,僅僅是背景關係輸出。

patch 介紹

patch 是一個可以將 diff 生成的補丁應用到源檔案,生成一個打過補丁版本的檔案。語法:

  1. patch [oiption] [originalfile [patchfile]]

常用引數:

◈ -i 指定補丁檔案
◈ -pNum 在 diff 生成的補丁中,第一二行是檔案資訊,其中檔案名是可以包含路徑的,例如 --- /tmp/test1 2018-05-12 18:39:41.508375114 +0800 其中 -p0 代表完整的路徑 /tmp/test1,而 -p1 則指 tmp/test1-pN 依此類推
◈ -E 刪除應用補丁後為空檔案的檔案
◈ -o 輸出到一個檔案而不是直接改寫檔案

應用

awesome 桌面 3.5 與 4.0 之間的升級是不相容的,所以在升級完 4.0 以後,awesome 桌面部分功能無法使用,因此需要遷移到新配置,接下來則應用 diff 與 patch 實現遷移,當然你也可以單純使用 diff 找出不同,然後手動修改新配置。

現在有以下幾個檔案:

◈ rc.lua.3.5 3.5 版本的預設配置檔案,未修改
◈ rc.lua.myconfig 基於 3.5 版本的個人配置檔案
◈ rc.lua.4.2 4.2 新預設配置,未修改

思路為利用 diff 提取出個人配置與 3.5 預設配置檔案的增量補丁,然後把補丁應用在 4.2 的檔案上實現遷移。

製作補丁

  1. $ diff -urN rc.lua.3.5 rc.lua.myconfig  > mypatch.patch

應用補丁

  1. $ patch rc.lua.4.2 -i mypatch.patch -o rc.lua

  2. patching file rc.lua (read from rc.lua.4.2)

  3. Hunk #1 FAILED at 38.

  4. Hunk #2 FAILED at 55.

  5. Hunk #3 succeeded at 101 with fuzz 1 (offset 5 lines).

  6. Hunk #4 succeeded at 276 with fuzz 2 (offset 29 lines).

  7. 2 out of 4 hunks FAILED -- saving rejects to file rc.lua.rej

顯然應用沒有完全成功,其中在 38 行以及 55 行應用失敗,並記錄在 rc.lua.rej 裡。

  1. $ cat rc.lua.rej

  2. --- rc.lua.3.5  2018-05-12 19:15:54.922286085 +0800

  3. +++ rc.lua.myconfig 2018-05-12 19:13:35.057911463 +0800

  4. @@ -38,10 +38,10 @@

  5. -- {{{ Variable definitions

  6. -- Themes define colours, icons, font and wallpapers.

  7. -beautiful.init("@AWESOME_THEMES_PATH@/default/theme.lua")

  8. +beautiful.init("~/.config/awesome/default/theme.lua")

  9. -- This is used later as the default terminal and editor to run.

  10. -terminal = "xterm"

  11. +terminal = "xfce4-terminal"

  12. editor = os.getenv("EDITOR") or "nano"

  13. editor_cmd = terminal .. " -e " .. editor

  14. @@ -55,18 +55,18 @@

  15. -- Table of layouts to cover with awful.layout.inc, order matters.

  16. local layouts =

  17. {

  18. -    awful.layout.suit.floating,

  19. -    awful.layout.suit.tile,

  20. -    awful.layout.suit.tile.left,

  21. -    awful.layout.suit.tile.bottom,

  22. -    awful.layout.suit.tile.top,

  23. +--    awful.layout.suit.floating,

  24. +--    awful.layout.suit.tile,

  25. +--    awful.layout.suit.tile.left,

  26. +--    awful.layout.suit.tile.bottom,

  27. +--    awful.layout.suit.tile.top,

  28.     awful.layout.suit.fair,

  29.     awful.layout.suit.fair.horizontal,

  30.     awful.layout.suit.spiral,

  31.     awful.layout.suit.spiral.dwindle,

  32.     awful.layout.suit.max,

  33.     awful.layout.suit.max.fullscreen,

  34. -    awful.layout.suit.magnifier

  35. +--    awful.layout.suit.magnifier

  36. }

  37. -- }}}

這裡是主題,終端,以及常用佈局的個人設定。

修正補丁

再次透過對比補丁檔案與 4.2 檔案,發現 38 行區塊是要刪除的東西不匹配,而 55 行區塊則是背景關係與要刪除的內容均不匹配,導致不能應用補丁,於是手動修改補丁

  1. $ vim mypatch.patch

  1. --- rc.lua.3.5  2018-05-12 19:15:54.922286085 +0800

  2. +++ rc.lua.myconfig 2018-05-12 19:13:35.057911463 +0800

  3. @@ -38,10 +38,10 @@

  4. -- {{{ Variable definitions

  5. -- Themes define colours, icons, font and wallpapers.

  6. -beautiful.init(gears.filesystem.get_themes_dir() .. "default/theme.lua")

  7. +beautiful.init("~/.config/awesome/default/theme.lua")

  8. -- This is used later as the default terminal and editor to run.

  9. -terminal = "xterm"

  10. +terminal = "xfce4-terminal"

  11. editor = os.getenv("EDITOR") or "nano"

  12. editor_cmd = terminal .. " -e " .. editor

  13. @@ -55,18 +55,18 @@

  14. -- Table of layouts to cover with awful.layout.inc, order matters.

  15. awful.layout.layouts = {

  16. -    awful.layout.suit.floating,

  17. -    awful.layout.suit.tile,

  18. -    awful.layout.suit.tile.left,

  19. -    awful.layout.suit.tile.bottom,

  20. -    awful.layout.suit.tile.top,

  21. +--    awful.layout.suit.floating,

  22. +--    awful.layout.suit.tile,

  23. +--    awful.layout.suit.tile.left,

  24. +--    awful.layout.suit.tile.bottom,

  25. +--    awful.layout.suit.tile.top,

  26.     awful.layout.suit.fair,

  27.     awful.layout.suit.fair.horizontal,

  28.     awful.layout.suit.spiral,

  29.     awful.layout.suit.spiral.dwindle,

  30.     awful.layout.suit.max,

  31.     awful.layout.suit.max.fullscreen,

  32. -    awful.layout.suit.magnifier,

  33. +--    awful.layout.suit.magnifier,

  34.     awful.layout.suit.corner.nw,

  35.     -- awful.layout.suit.corner.ne,

  36.     -- awful.layout.suit.corner.sw,

  37. ....

  38. ....

輸出省略顯示,有興趣的讀者可以仔細與rc.lua.rej 檔案對比,看看筆者是怎樣改的。

再次應用補丁

  1. $ patch rc.lua.4.2 -i mypatch.patch -o rc.lua

  2. patching file rc.lua (read from rc.lua.4.2)

  3. Hunk #1 succeeded at 41 (offset 3 lines).

  4. Hunk #2 succeeded at 57 with fuzz 2 (offset 2 lines).

  5. Hunk #3 succeeded at 101 with fuzz 1 (offset 5 lines).

  6. Hunk #4 succeeded at 276 with fuzz 2 (offset 29 lines).

  7. $ cp rc.lua ~/.config/awesome/rc.lua  ### 打完補丁直接使用

總結

diff 與 patch 配合使用,能當增量備份,而且還可以將補丁分發給他人使用,而且在日常的軟體包打補丁也具有重要的意義,特別是核心補丁或者一些驅動補丁,打補丁遇到錯誤時候可以嘗試自己修改,已滿足自身特殊要求,修改的時候一定要抓住 2 個非常重要的要素:

☉ 要修改的內容是否匹配?特別是要刪除的
☉ 背景關係是否滿足,特別是距離要修改的地方前後一行,以及背景關係的行數是否滿足,預設是 3 行背景關係

贊(0)

分享創造快樂

© 2024 知識星球   網站地圖