linux下patch指令使用詳解---linux打更新檔指令
功能說明:修補檔案。
語 法:patch [-bceEflnNRstTuvZ][-B <備份字首字元串>][-d <工作目錄>][-D <标示符号>][-F <監别列數>][-g <控制數值>][-i <修補檔案>][-o <輸出檔案>][-p <剝離層級>][-r <拒絕檔案>][-V <備份方式>][-Y <備份字首字元串>][-z <備份字尾字元串>][--backup-if -mismatch][--binary][--help][--nobackup-if-mismatch][--verbose][原始檔案 <修補檔案>] 或 path [-p <剝離層級>] < [修補檔案]
補充說明:patch指令讓使用者利用設定修補檔案的方式,修改,更新原始檔案。倘若一次僅修改一個檔案,可直接在指令列中下達指令依序執行。如果配合修補檔案的方式則能一次修補大批檔案,這也是Linux系統核心的更新方法之一。
參 數:
-b或--backup 備份每一個原始檔案。
-B<備份字首字元串>或--prefix=<備份字首字元串> 設定檔案備份時,附加在檔案名稱前面的字首字元串,該字元串可以是路徑名稱。
-c或--context 把修補資料解譯成關聯性的差異。
-d<工作目錄>或--directory=<工作目錄> 設定工作目錄。
-D<标示符号>或--ifdef=<标示符号> 用指定的符号把改變的地方标示出來。
-e或--ed 把修補資料解譯成ed指令可用的叙述檔案。
-E或--remove-empty-files 若修補過後輸出的檔案其内容是一片空白,則移除該檔案。
-f或--force 此參數的效果和指定-t參數類似,但會假設修補資料的版本為新 版本。
-F<監别列數>或--fuzz<監别列數> 設定監别列數的最大值。
-g<控制數值>或--get=<控制數值> 設定以RSC或SCCS控制修補作業。
-i<修補檔案>或--input=<修補檔案> 讀取指定的修補問家你。
-l或--ignore-whitespace 忽略修補資料與輸入資料的跳格,空格字元。
-n或--normal 把修補資料解譯成一般性的差異。
-N或--forward 忽略修補的資料較原始檔案的版本更舊,或該版本的修補資料已使 用過。
-o<輸出檔案>或--output=<輸出檔案> 設定輸出檔案的名稱,修補過的檔案會以該名稱存放。
-p<剝離層級>或--strip=<剝離層級> 設定欲剝離幾層路徑名稱。
-f<拒絕檔案>或--reject-file=<拒絕檔案> 設定儲存拒絕修補相關資訊的檔案名稱,預設的檔案名稱為.rej。
-R或--reverse 假設修補資料是由新舊檔案交換位置而産生。
-s或--quiet或--silent 不顯示指令執行過程,除非發生錯誤。
-t或--batch 自動略過錯誤,不詢問任何問題。
-T或--set-time 此參數的效果和指定-Z參數類似,但以本地時間為主。
-u或--unified 把修補資料解譯成一緻化的差異。
-v或--version 顯示版本資訊。
-V<備份方式>或--version-control=<備份方式> 用-b參數備份目标檔案後,備份檔案的字尾會被加上一個備份字元串,這個字元串不僅可用-z參數變更,當使用-V參數指定不同備份方式時,也會産生不同字尾的備份字元串。
-Y<備份字首字元串>或--basename-prefix=--<備份字首字元串> 設定檔案備份時,附加在檔案基本名稱開頭的字首字元串。
-z<備份字尾字元串>或--suffix=<備份字尾字元串> 此參數的效果和指定-B參數類似,差别在于修補作業使用的路徑與檔案名若為src/linux/fs/super.c,加上backup/字元串後,檔案super.c會備份于/src/linux/fs/backup目錄裡。
-Z或--set-utc 把修補過的檔案更改,存取時間設為UTC。
--backup-if-mismatch 在修補資料不完全吻合,且沒有刻意指定要備份檔案時,才備份檔案。
--binary 以二進制模式讀寫資料,而不通過标準輸出裝置。
--help 線上幫助。
--nobackup-if-mismatch 在修補資料不完全吻合,且沒有刻意指定要備份檔案時,不要備份檔案。
--verbose 詳細顯示指令的執行過程。
patch,是打更新檔的指令,有很多用法,見幫助#man patch
patch -p0 (“p”指的是路徑,後面的數字表示去掉路徑的第幾部分。0,表示不去掉,為全路徑)
patch -p1 (“p”後面的數字1,表示去掉前第一個路徑)fetch http://people.freebsd.org/~delphij/misc/patch-bge-releng62
fetch http://people.freebsd.org/~delphij/misc/patch-bce-watchdog-rewritecd /sys/dev/bge
fetch ...
patch -p0 < ...fetch http://people.freebsd.org/~delphij/misc/patch-tcp_auto_buf-20061212-RELENG_6.diff
patch -p < patch-tcp_auto_buf-20061212-RELENG_6.diff
也可以把檔案中的目錄全改成系統已在的目錄如/usr/src/sys.....注意:
1,确認目錄
然後确認目錄,如不在預設目錄下,就寫下要打更新檔的目前絕對目錄。如/usr/src/sys/dev/bge/if_bce.c2,P的使用
可以使用不帶數字的參數。
patch 後的軟體安裝
telnetd伺服器的問題及更新檔 在目前FreeBSD所有版本中,也就是FreeBSD 5.0、FreeBSD 4.3、FreeBSD 4.2、FreeBSD 4.1.1、FreeBSD 4.1、FreeBSD 4.0、FreeBSD 3.x、FreeBSD 2.x的版本,其telnetd守護程序中存在一個緻命的緩沖區溢出漏洞,該問題是由于telnetd在處理telnet協定選項的函數中沒有進行有效的邊界檢查,當使用某些選項(\'AYT\')時,可能發生緩沖區溢出。這會導緻遠端root級别的安全威脅。
是以,如果一定要使用telnet服務的話,必須為伺服器打上最新的patch,該patch可以從以下連結獲得: (注:通常有兩個版本的telnetd伺服器,有crypto及無crypto的版本,是以需要判斷主機使用的是哪種版本的telnetd,這通常可以通過察看src檔案來判斷,比如# ls /usr/src/crypto/telnet/telnetd,如果不存在,則說明使用的是無crypto的版本了,在判别清楚之後再分别下載下傳相關更新檔檔案) crypto版本更新檔:
ftp://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-01:49/telnetd-crypto.patch
ftp://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-01:49/telnetd-crypto.patch.asc patch方法:
# cd /usr/src/
# patch -p < /path/to/patch
# cd /usr/src/secure/libexec/telnetd
# make depend && make all install 無crypto版本更新檔:
ftp://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-01:49/telnetd.patch
ftp://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-01:49/telnetd.patch.asc patch方法:
# cd /usr/src/libexec/telnetd
# make depend && make all install 例子來源http://toby.bokee.com/檔案:isp1161-2.6.12.patch(在/root下)
由于patch檔案的首行已經指明了路徑,是以根據目前所在的目錄,加不同的參數使用patch指令:
1:如果目前的目錄是和linux-2.6.12的同級目錄:
[root@kcn-110mw]#patch -p0 </root/isp1161-2.6.12.patch
2:如果目前的目錄為 linux-2.6.12/:
[root@kcn-110mw]#patch -p1 </root/isp1161-2.6.12.patch
3:如果目前的目錄為 linux-2.6.12/drivers/:
[root@kcn-110mw]#patch -p2 </root/isp1161-2.6.12.pathc
0,1,2,是指略去的patch檔案中的前幾級目錄。
ln 指令的使用
這是linux中一個非常重要的指令。它的功能是為某一個檔案在另外一個位置建立一個不同的連結,這個指令最常用的參數是-s,具體用法是:ln -s 源檔案 目标檔案。
當我們需要在不同的目錄,用到相同的檔案時,我們不需要在每一個需要的目錄下都放一個必須相同的檔案,我們隻要在某個固定的目錄放上該檔案,然後在其它的目錄下用ln指令連結(link)它就可以,不必重複的占用磁盤空間。
例如:ln -s /bin/less /usr/local/bin/less
-s 是代号(symbolic)的意思。
這裡有兩點要注意:
第一,ln指令會保持每一處連結檔案的同步性。也就是說,不論你改動了哪一處,其它的檔案都會發生相同的變化。
patch附帶有一個很好的幫助,其中羅列了很多選項,但是99%的時間隻要兩個選項就能滿足我們的需要:
patch -p1 < [patchfile]
patch -R < [patchfile] (used to undo a patch)
-p1選項代表patchfile中檔案名左邊目錄的層數,頂層目錄在不同的機器上有所不同。要使用這個選項,就要把你的patch放在要被打更新檔的目錄下,然後在這個目錄中運作path -p1 < [patchfile]。來自Linux核心patch的一個簡短的引用可以這樣實作:
diff -u --recursive --new-file v2.1.118/linux/mm/swapfile.c linux/mm/swapfile. c--- v2.1.118/linux/mm/swapfile.c Wed Aug 26 11:37:45 1998 +++ linux/mm/swapfile.c Wed Aug 26 16:01:57 1998 @@ -489,7 +489,7 @@
int swap_header_version;
int lock_map_size = PAGE_SIZE;
int nr_good_pages = 0; - char tmp_lock_map = 0; + unsigned long tmp_lock_map = 0;
應用來自本段中使用-p1開關拷貝的patch可以有效地減短patch定位的路徑;patch會查找目前目錄下一個名為/mm的子目錄,接着應該會在這兒發現swapfile.c檔案,然後等待打更新檔。在這個過程中,以破折号(“-”号,譯者注)開始的行會被一個以加号(“+”号,譯者注)開始的行代替。一個典型的patch會包含對多個檔案的更新,每個部分中都由對兩個版本的檔案運作diff -u指令的輸出結果組成。
patch在操作時把自己的輸出結果顯示在螢幕上,但是這種輸出通常都滾屏太快,來不及觀看。原來準備patch的檔案名為*.orig,新的patch檔案會覆寫這個初始檔案名。
打更新檔的問題
使用不同版本的patch問題來源可能不同,所有的版本在網絡上都是可用的。Larry Wall近年來已經不再做很多工作來更新patch了,這可能是由于他最後發行的一個版本在大部分情況下都能正常運作。最近幾年以來,一直是GNU項目的 FSF程式員發行新版本的patch。他們首先修訂有問題的patch,但是我最近一直使用沒有問題的2.5版本(這是Debian2.0的發行版本号)。過去,我的2.1版本也一直運作的很好。目前的GNU patch的版本可以從GNU FTP站點上擷取,然而大部分人都隻使用他們Linux發行版中所提供的版本。
讓我們假定你已經對一個目錄下的源程式檔案進行了patch修補工作,但是patch并沒有清晰地發揮作用。這可能會偶然發生,在打更新檔的過程中會顯示錯誤資訊,其中帶有行号,說明哪一個檔案出現了問題。有時錯誤是很明顯的,例如缺少了分号,這種錯誤可以不費多大力氣就能改正。另外一種可能是從 patch部分删除了産生問題的部分,但是這樣根據所涉及到的檔案的不同可能會正常工作,也可能不能正常工作了。
另外一種常見的錯位為:假設你有一個未使用tar打包的核心源程式檔案,在/linux/arch/下浏覽各個子目錄時你會發現各種機器體系結構子目錄,例如alpah、sparc等等。如果你和大多數Linux使用者一樣,使用的是Intel的處理器(或者是Intel系列),你可以決定删除這些目錄,這些目錄對于編譯你特殊的核心并不需要,隻是白白占用了磁盤空間。一段時間之後發行了一個新的核心patch,此時試圖進行patch操作,當它發現不能找到自己打更新檔需要的Alpha或者PPC檔案,就會停頓下來。幸運的是patch在這些地方允許使用者參與,它會詢問Skip this patch?回答y,patch就可以按照正确的路徑繼續執行。也許你需要回答這個問題很多次,是以允許自己不需要的目錄保留在磁盤上是一種很好的方給核心打更新檔的技巧
很多Linux使用者使用patch都主要是給核心源程式打更新檔,是以有一些技巧可以使用。可能最簡單的方法是使用shell腳本給核心打更新檔,這可以在核心源程式樹中的/scripts子目錄中找到。這種友善的、編寫良好的腳本是由Nick Holloway在1995年編寫的;兩年以後,Adam Sulmicki增加了多種壓縮格式的支援,包括*.bz、*.bz2、compress、gzip和無格式文本(也就是已經解壓的patch)。這個腳本假定在你使用新版本的patch時,你的核心源程式是在/usr/src/linux目錄中。這些預設值可以通過這種格式的指令行開關覆寫:patch -kernel [sourcedir [patchdir] ]。如果任何一部分的patch失敗,對核心打更新檔的過程都會失敗,但是如果patch清晰地起作用,它就會調用find,這會删除所有的patch留下的*.orig檔案。
如果你準備檢視指令的輸出,或者可能你希望保留*.orig檔案直到你确定打過更新檔的源程式編譯已經通過,按照我的經驗,直接運作patch(正如前面介紹的一樣,patch位于核心源程式的最高目錄)是很可靠的。為了避免對patch進行解壓,在使用之前,可以使用這樣一個技巧:
gzip -cd patchXX.gz | patch -p1
或者
bzip2 -dc patchXX.bz2 | patch -p1
在使用patch之後,可以使用find程式來檢測被拒絕的檔案:
find . -name *.rej
第一次使用這個指令,文法可能有些不清楚。點号(“.”)說明find應該查找目前目錄并遞規查找目前目錄之下的所有子目錄。記住,點号前後都應該有一個空格。通配符*号前面的反斜線把星号轉義出來,以免shell會搞混,星号是有其它意義的。如果find找到了任何的*.rej檔案,它就會把檔案名列印到螢幕上。如果沒有任何輸出find就退出了,那麼就差不多能确定patch正确發揮作用了。
find的另外一個工作是删除*.orig檔案:
find . -name *.orig -print0 | xargs -0r rm -f
這個指令敲起來相當麻煩,可以使用一個新的shellalias.html' target='_blank'>别名來代替這個指令。在你的~/.bashrc檔案中類似這樣的一行: