在給客戶提供支援人員工作的時候,常會遇到需要修改各種不同的設定檔。過去的方式,通常是描述修改的地方,然後由使用者自行修改,或使用sed等工具寫一個指令碼給使用者運行。但這樣會帶來一些問題:如果使用者不會vi,或者他理解錯、找錯配置的位置,這樣帶來的問題可能更難預計。
此時,或許可以試試我的方法,借用diff和patch直接幫使用者修改,然後把產生的“patch補丁”發給他運行即可。這樣工作量小,而且也能控制修改後的結果,當然也方便Email發送咯。
一、介紹
diff和patch是一對工具,在數學上來說,diff是對兩個集合的差運算,patch是對兩個集合的和運算。diff比較兩個檔案或檔案集合的差異,並記錄下來,產生一個差異檔案,這也是我們常說的補丁檔案。補丁檔案能運用於原來的兩個集合之一,從而得到另一個集合。
舉個例子來說檔案A和檔案B,經過diff之後產生了補丁檔案C,那麼著個過程相當於 A -B = C ,那麼patch的過程就是B+C = A 或A-C =B。
因此我們只要能得到A, B, C三個檔案中的任何兩個,就能用diff和patch這對工具產生另外一個檔案。
二、使用
執行個體說明是最快的方法,假設現在有a、b兩個檔案,內容如下:
引用$ cat a
123456
$ cat b
abcdef
其中a是使用者發給我的檔案,而b是我修改後的檔案。
那我們可以這樣產生c檔案:
$ diff -Naur a b > c
然後,可以把c檔案發給使用者,運行如下的命令即可自行修改a->b:
$ patch -p0 a < c
patching file a
結果如下:
$ cat a
abcdef
三、恢複
上面的操作很簡單吧。那如果萬一a修改有誤,如何恢複呢?通過前面的說明可以知道,通過c檔案是可以直接恢複的:
引用$ patch -R -p0 a < c
patching file a
$ cat a
123456
可以看到使用diff和patch是比較安全的,請注意-R選項哦!
另外,diff產生的c檔案是有記錄檔案名稱的,在不指定原檔案的情況下,可以自動識別:
$ patch -p0 < c
patching file a
反了會這樣:
$ patch -p0 b < c
patching file b
Reversed (or previously applied) patch detected! Assume -R? [n] n
Apply anyway? [n] n
Skipping patch.
1 out of 1 hunk ignored -- saving rejects to file b.rej
所以,一般是不會搞錯新舊檔案的。
四、路徑問題
很多時候,我們還會遇到一個問題。就是為了防止檔案修改錯,或需要同時修改多個檔案,可能會建立多一層目錄,例如:
引用$ ls -R
.:
new old
./new:
b
./old:
a
diff是可以識別路徑:
$ diff -Naur old/ new/ > c
補丁需要這樣打:
$ cd old/
$ patch -p1 < ../c
patching file a
patching file b
結果如下:
引用$ ls
b
$ cat b
abcdef
※注意咯,這樣會把整個目錄的檔案內容和檔案名稱都改掉的。另外,如果目錄中有多個檔案,除了new目錄中的空檔案外,會把old下的所有檔案都換成new的檔案和內容;new沒有,而old有的檔案,會刪除。
引用-pN參數的意思是:取消N層目錄,也就是把old/改為./
五、注意事項
引用1、在patch之前不要對原檔案進行任何修改,否則補丁可能會失效;
2、如果做了多個補丁,請注意先後順序,要按次序打才行;
3、如果打補丁出現問題,會產生.rej檔案,其中包括原檔案和補丁差異的地方。