2010年4月25日 星期日

dpkg速記

deb的基本安裝過程:
dpkg是Debian底層的套件管理程式,其上還有強大的apt,在其上更有非常強大的aptitude管理系統。Debian系列的linux,如Ubuntu, B2D, LinuxMint等,都是使用dpkg作為底層的套件管理程式。不過由於apt以及aptitude過於強大,許多使用者對於dpkg的熟悉度往往少於Redhat系的使用者對於rpm的熟悉度;本文僅作為一個Debian的死忠支持者對dpkg指令的一篇速記,希望對於Debian迷以及Ubuntu Linux的技術人員亦能有所幫助。
dpkg能用來查詢、安裝以及設定deb檔;如同rpm,dpkg亦使用dpkg資料庫紀錄每個套件安裝、設定、移除等詳細資訊。一個標準的deb檔命名方式如下:

Filename_version-release_arch.deb
例如madedit_0.2.9-1_amd64.deb,madedit就是套件名稱,0.2.9為版本號,1為釋出番號,amd64則表示x86_64位元的平台。安裝一個deb的流程大致如下:
  1. 解開control file
  2. 從dpkgdb檢查系統是否已安裝此套件且版本相同;如果有,則執行prerm script,再執行preinst script。
  3. 備份舊的binaries,解開新的bineries並複製到設計好的位置。
  4. 從dpkgdb檢查系統是否已安裝此套件但版本不同;如果有,則執行postrm script。
  5. 備份舊的config檔,解開新的config檔並複製到設計好的位置。
  6. 執行postinst script。
dpkg有兩個姊妹:dpkg-deb以及dpkg-query。不過dpkg的action以及options能涵蓋大部分這兩個指令的功能,因此本文就僅提dpkg常用的功能。

安裝

dpkg的基本語法是:

dpkg action options
例如
dpkg --install --force-architecture foo.deb
--install對於dpkg而言是action,而--force-architecture則是action的微調選項。 dpkg的安裝並不進行gpg公開金鑰的驗證,而是在apt或是aptitude的部份進行檢查,因此有別於rpm系列的模式。安裝一個deb檔只需要-i(--install)命令:
dpkg -i foo.deb
一個deb的安裝大致可將上述流程一分為二:先解開這個deb檔到檔案系統中並寫入到dpkgdb裡,然後才進行設定。事實上,--install可以手動分成兩個步驟完成:
dpkg --unpack foo.deb
dpkg --configure foo
當然,你也可以在執行一次configure:
dpkg-reconfigure foo
很可惜,dpkg並不支援安裝一個網路上的deb檔,如果你想學rpm的方式:
dpkg -i http://altruistic.lbl.gov/mirrors/ubuntu/pool/universe/x/xosview/xosview_1.8.3+debian-18_i386.deb
你一定會得到錯誤訊息:
dpkg: error processing http://altruistic.lbl.gov/mirrors/ubuntu/pool/universe/x/xosview/xosview_1.8.3+debian-18_i386.deb (--install):
 cannot access archive: No such file or directory
Errors were encountered while processing:
 http://altruistic.lbl.gov/mirrors/ubuntu/pool/universe/x/xosview/xosview_1.8.3+debian-18_i386.deb

升級

嚴格來說,dpkg並沒有從deb去升級套件的指令。從deb的安裝流程來看,dpkg只要遇到版本比系統上的還新,就會自動移除舊的套件並安裝新的套件,備份舊的設定檔並套用新的設定檔。當然,自動移除舊套件這類prerm/preinst script都需要deb套件維護人員的細心維護。如果deb被粗心的維護,這個流程恐怕就不能如預期跑完。

重新安裝/強迫安裝

dpkg並沒有重新安裝這個觀念。使用--install遇到同版本的套件,並不會重新安裝,但是卻會再次執行--configure。如果想要重新安裝而不透過apt/aptitude,則需要移除套件才能再次安裝。
忽略套件的衝突進行強迫安裝。

dpkg -i --force-conflicts foo.deb
忽略套件的相依性進行強迫安裝。
dpkg -i --force-depends foo.deb
忽略套件相依性的版本問題。如果只是版本問題而非缺乏套件相依性,可以用這個option試試看。
dpkg -i --force-depends-version foo.deb
忽略套件的相依性,並且將套件的Desired status(稍後會提到)設定為hold進行強迫安裝。
dpkg -i --force-hold --force-depends foo.deb
更新設定檔時保留舊設定。最常用於安裝新版本的套件。如果想用新的設定檔,則改為--force-confnew。
dpkg -i --force-confold foo.deb
如果你是x86_64的機器,可是binaries只有for x86且沒有source code可供編譯,可以試試看安裝x86的deb。
dpkg --install --force-architecture foo_i386.deb
強迫安裝一個更舊的套件。需注意降級套件並不會顯示任何套件衝突或是相依性問題。使用時不要拿系統主要的套件來嘗試。
dpkg --install --force-downgrade foo.deb
強迫安裝一個套件。利用--refuse停止複寫系統內的檔案,並用--force強制忽略相依性及衝突性來安裝deb檔。
dpkg --install --refuse-overwrite --force-depends --force-conflicts foo.deb

不過這些強迫安裝的套件,都會因為使用apt/aptitude而被移除。

LPI level I也喜歡考這幾個options:
指定一個deb資料夾來安裝(-R/--recursive):

dpkg -iR foo/
安裝時若遇相依性問題,一律拒絕版本降級(-G/--refuse-downgrade):
dpkg -iG foo.deb
安裝時若遇到相同版本的套件,就略過不處理(-E/--skip-same-version):
dpkg -iE *.deb
檢視未安裝完全的套件(-C/--audit):
dpkg -C
-C/--audit並沒有額外options,如果檢視的結果沒有任何輸出,表示所有套件均正確被安裝及設定。

查詢已安裝的套件

1.以最常見的vim為例,查詢某套件的安裝狀態訊息(-l, --list)

dpkg -l vim
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Cfg-files/Unpacked/Failed-cfg/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ 名稱         版本         簡介
+++-==============-==============-============================================
ii  vim            2:7.2.245-2ubu Vi IMproved - enhanced vi editor
輸出結果的狀態欄位為"ii "共三個欄位。
第一個欄位為Desire status(也稱為Selection status),是系統管理員設定某套件將要執行的更動,例如
  1. u(unknown)
  2. i(install)
  3. r(remove)
  4. p(purge,連設定檔也移除)
  5. h(hold,維持版本號)
這個欄位是被特別設定的。例如你要把vim的Desired status設定成hold,也就是不更新此套件:
echo "vim hold" | dpkg --set-selections
可以在試試看dpkg -l vim:
hi  vim            2:7.2.245-2ubu Vi IMproved - enhanced vi editor
可以發現Desired status已經是hold住了。--set-selections只接受stdin,若想知道某個套件的Desired status,就使用--get-selections吧:
dpkg --get-selections vim
vim      install
第二個欄位為Package status(或稱為actual status),是套件目前的狀態
  1. N(not-installed)
  2. dpkg --purge所致,不留設定檔。
  3. C(config-files)
  4. dpkg --remove所致,只剩下設定檔了。
  5. H(half-installed)
  6. 不完全安裝,常見於其他套件執行--force-breaks所影響。
  7. U(unpacked only)
  8. dpkg --unpack之後的結果。
  9. F(half-configured or failed configured)
  10. 是一個設定失敗的套件,通常會是一個服務。
  11. A(triggers-awaited)
  12. 表示下次系統執行apt/aptitude時,會等待某個套件的觸發而觸發,使之變更到Selection status。
  13. P(triggers-pending)
  14. 表示下次系統執行apt/aptitude時會觸發這個套件使之變更到Selection status。
  15. i(installed)
  16. 一個正常的安裝狀態。
第三個欄位為Package Flags(套件旗標),只有一個flag:
r(reinst-required)
出現這個flag表示該套件被標示為broken,他不能夠被移除,並且會嘗試在下次執行apt/aptitude時重新安裝。
我們常用dpkg -l | grep foo來查詢某個套件的狀態,而不要列出一大堆不必要的欄位資訊。

2.查詢某套件的詳細資訊,包含相依性、衝突套件等(-p, --print-avail/-s, --status)
dpkg -p(-s) vim
Package: vim
Priority: optional
Section: editors
Installed-Size: 1516
Maintainer: Debian Vim Maintainers 
Architecture: i386
Version: 1:7.1.314-3+lenny2
Replaces: vim-common (<< 1:7.1-175+1)
Provides: editor
Depends: vim-common (= 1:7.1.314-3+lenny2), vim-runtime (= 1:7.1.314-3+lenny2), libacl1 (>= 2.2.11-1), libc6 (>= 2.7-1), libgpm2 (>= 1.20.4), libncurses5 (>= 5.6+20071006-3), libselinux1 (>= 2.0.59)
Suggests: ctags, vim-doc, vim-scripts
Conflicts: vim-common (<< 1:7.1-175+1)
Size: 776664
...描述省略

3.列出套件所包含的檔案(-L, --listfile)
dpkg -L vim
/usr
/usr/bin
/usr/bin/vim.basic
/usr/share
/usr/share/bug
/usr/share/bug/vim
/usr/share/bug/vim/presubj
/usr/share/doc
/usr/share/lintian
/usr/share/lintian/overrides
/usr/share/lintian/overrides/vim
/usr/share/doc/vim

4.查詢某檔案由哪個套件提供(-S, --search)
dpkg -S /etc/apache2/apache2.conf
apache2.2-common: /etc/apache2/apache2.conf

查詢一個deb檔

1.查詢一個deb檔所包含的檔案(-c, --contents)

dpkg -c xosview_1.8.3+debian-18_i386.deb
drwxr-xr-x root/root         0 2009-09-28 21:17 ./
drwxr-xr-x root/root         0 2009-09-28 21:16 ./etc/
drwxr-xr-x root/root         0 2009-09-28 21:16 ./etc/X11/
drwxr-xr-x root/root         0 2009-09-28 21:16 ./etc/X11/app-defaults/
-rw-r--r-- root/root     11382 2009-09-28 21:16 ./etc/X11/app-defaults/XOsview
drwxr-xr-x root/root         0 2009-09-28 21:16 ./usr/
drwxr-xr-x root/root         0 2009-09-28 21:16 ./usr/share/
drwxr-xr-x root/root         0 2009-09-28 21:16 ./usr/share/applications/
-rw-r--r-- root/root       153 2009-09-28 21:16 ./usr/share/applications/xosview.desktop
drwxr-xr-x root/root         0 2009-09-28 21:16 ./usr/share/pixmaps/
-rw-r--r-- root/root     11447 2009-09-28 21:16 ./usr/share/pixmaps/xosview.xpm
2.查詢一個deb檔的詳細資訊(-I, --info)
dpkg -I xosview_1.8.3+debian-18_i386.deb
(-I是大寫的i,不是小寫的L喔!)
 new debian package, version 2.0.
 size 110050 bytes: control archive= 1210 bytes.
      30 bytes,     1 lines      conffiles            
     704 bytes,    16 lines      control              
     717 bytes,    11 lines      md5sums              
     185 bytes,     7 lines   *  postinst             #!/bin/sh
     160 bytes,     5 lines   *  postrm               #!/bin/sh
 Package: xosview
 Version: 1.8.3+debian-18
 Architecture: i386
 Maintainer: Ubuntu Developers 
 Original-Maintainer: Kartik Mistry 
 Installed-Size: 328
 Depends: libc6 (>= 2.4), libgcc1 (>= 1:4.1.1), libstdc++6 (>= 4.4.0), libx11-6
 ...以下省略

移除(--remove/--purge)

dpkg -r foo
刪除一個套件。需記得dpkg不會幫您解決相依性、套件衝突問題;如果有這些問題,dpkg -r並不會成功動作。
dpkg -P foo
刪除一個套件。並且連設定檔一同刪除。

解開deb(dpkg -x):

dpkg -x foo.deb /path
解開這個deb安裝後的目錄樹。但是真正能控制deb的設定檔並不會被解出來。要一窺deb控制檔的奧秘,你必須使用ar:
ar x foo.deb
可以發現有control.tar.gz、data.tar.gz、debian-binary這三個檔案,其中control.tar.gz便包含了許多安裝前後的script:
./postinst
./postrm
./conffiles
./md5sums
./control
而data.tar.gz就是真正要安裝到檔案系統的內容。

參考文獻:
1. Debian System -- concept and technology
2. A practical guide to Ubuntu Linux
3. Man page of dpkg
4. 次世代Ubuntu Linux完全手冊,第五章