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完全手冊,第五章

2010年4月24日 星期六

YUM筆記

YUM簡史

YUM(Yellow dog Updater, Modified)是Redhat系列的linux最重要的套件管理程式,他的前身是YUP(Yellow dog UPdater)。Yellow Dog很多人是很陌生的,他是在早期運行在IBM的power平台上的linux,也是使用rpm based。當時能夠跑在power上的linux大概就只有Debian以及Redhat/Fedora Linux;後來在社群不斷地維護、改善下,就產生了重大的改版--YUM。

很顯然的,YUP或是YUM的出現是因為rpm的相依性、版本、套件間衝突的問題用手動很難解決,必須要依靠一個機制來自動替我們解決所有相依性地獄(dependency hell)的問題。yum提供的服務大致有四項:

  1. 自動解決相依性問題
  2. 能夠用command自動化管理,也能有圖形化介面(pirut)
  3. 能夠管理多個套件庫來源
  4. 能夠跟rpm一樣精確的管理套件的版本以及適用平台的種種情況

Repostories

一個Redhat Linux標準的repostories設定檔,是放置在/etc/yum.repos.d/底下,任何以.repo結尾的檔案都會被視為一個套件庫。以一個RHEL5.repo為例,他的格式如下:

[Server]
name= Server catagory
enable = 1
baseurl=http://192.168.2.254/RHEL5/Server/
gpgcheck=0

[VT]
name= Virtualization catagory
enable = 1
baseurl=http://192.168.2.254/RHEL5/VT/
gpgcheck=0

[Cluster]
name= Cluster catagory
enable = 1
baseurl=http://192.168.2.254/RHEL5/Cluster/
gpgcheck=0

[ClusterStorage]
name= ClusterStorage catagory
enable = 1
baseurl=http://192.168.2.254/RHEL5/ClusterStorage/
gpgcheck=0
其中,[XX]就是yum認定的repo category名稱;利用enable變數可以開關一個category。習慣上相同來源不同的category會放在同一個.repo便於維護,當然你也可以將所有來源寫成同一個檔案,或是每個category都獨立成一個.repo,yum都能夠正確解讀。
想知道有哪些categories是enable/disable,或是全部列出,可以使用repolist:
yum repolist all
repo id             repo name                                    status
Cluster             Cluster catagory                             enabled:     32
ClusterStorage      ClusterStorage catagory                      enabled:     30
RHEL5               RHEL5                                        disabled
Server              Server catagory                              enabled:  2,797
VT                  Virtualization catagory                      enabled:     34
rhel-debuginfo      Red Hat Enterprise Linux 5Server - i386 - De disabled
rhel-debuginfo-beta Red Hat Enterprise Linux 5Server Beta - i386 disabled
rpmforge            Red Hat Enterprise 5Server - RPMforge.net -  enabled: 10,305
rpmforge-testing    Red Hat Enterprise 5Server - RPMforge.net -  disabled
repolist: 13,198

安裝(install)

yum有著非常直觀的命令列:install用來安裝數個套件:

yum install foo1 foo2 foo3
如果你的機器是x86_64,你還可以選擇安裝x86版本的套件,此時只要在多指定名稱即可:
yum install f001.x86_64 f002.x86 f003
對於沒有指定平台的套件,如果套件庫兩者都存在,則兩種平台都會安裝;因此還是強烈建議把平台名稱也寫上去。yum的運行機制會先更新yumdb,然後從dbcache裡得知所有套件資訊,因此當你執行yum install foo時,yum已經更新了他的yumdb,並且列出滿足安裝該套件所需要額外安裝的套件,並等待徵求你的同意。有時候你想自動回答yes,那麼就加個-y:
yum install foo3 -y
不過如果你沒有匯入gpg公開金鑰,yum下載完rpm會拒絕你繼續安裝。解決的方法是在.repo檔裡設定gpgcheck=0,或是直接使用nogpgcheck:
yum install foo3 --nogpgcheck -y
如果想忽略訊息,就加個-q吧。當然,你可以用yum安裝一個rpm,讓yum幫你解決惱人的相依性問題(如果yum可以解決的話):
yum localinstall foo3-1.2.3-5.el5-x86_64.rpm
or
yum localupdate foo3-1.2.3-9.el5-x86_64.rpm
yum也支援安裝一個群組套件,這比較少用到,除非你知道有哪些群組套件可用:
yum groupinstall "GNOME Desktop Environment"
當然,yum也可以讓你很容易的重新安裝:
yum reinstall foo

更新(update/upgrade)

更新是很重要的事情。除非一個系統只專門為了某項服務而設立(例如網格計算之類的高速電腦),或是在一個非常封閉的環境裡(例如無法連入的私有網路),否則更新套件以及安全性更新是很重要的。update就是最常用的更新指令:

yum update foo2 foo2
這樣一來便能夠更新這兩個套件。如果不加任何套件名稱,則系統內所有套件都會被更新。yum也可以讓你只看看有哪些東西需要更新,而不會真的更新:
yum check-update
另一個類似的用法:upgrade
yum upgrade
其實等同於
yum update --obsoletes
讓套件的更新會刪除已淘汰(repo不再被維護)的舊套件。通常這個指令只建議做同版本的升級(例如CentOS 4.3->4.4),如果想要從CentOS4.4升級到目前的5.4,恐怕還是建議拿光碟升級或重灌系統。
或是讓你降級安裝:
yum downgrade foo1

許多關鍵的server並不希望更新kernel或是gcc版本,我們可以從yum的設定檔下手:在/etc/yum.conf多加一行
exclude=kernel gcc
就可以防止被yum升級。

移除(remove/erase)

利用remove或是erase:

yum remove foo1 -y
利用yum remove比rpm -e來得方便多了,因為yum能自動幫我們解決相依性的問題。

查詢(list/search/info)

list可使用的對象分成七大類:installed(已安裝套件), available(所有repos裡的套件), updates(可供更新套件), extras(已安裝但不在repos裡), obsoletes(系統內已被repos廢棄的套件), recent(新被加入到repos的套件)以及all(所有安裝到系統的套件)。list可提供套件名稱的模糊搜尋。要查看有沒有可以更新的套件:

yum list updates
查看有沒有安裝http:
yum list installed http*
查看整個套件庫有多少套件:
yum list avaliable | wc -l
search則是比list提供更廣義的搜尋。利用search可以提供套件名稱、描述、摘要以及與該套件相關的模糊搜尋。
yum search python
便會發現所有欄位包含python都會被納入搜尋範圍。
info會列出套件的詳細資訊。如果只下yum info,則會列出所有套件庫內的套件資訊,那是非常龐大且沒有幫助的訊息。一樣可以用list的規範:
yum info installed | grep nfs
當然,info也可以直接指定套件名稱,但也僅限於套件名稱的模糊搜尋:
yum info nfs*
其他的類別就各憑需求去執行囉。

進階查詢(provides/whatprovides)

provides與whatprovides是相同的意義,通常用在尋找某個檔案是由哪個套件所帶來的

yum provides /etc/passwd
setup-2.5.58-1.el5.noarch : A set of system configuration and setup files.
Repo        : Server
Matched from:
Filename    : /etc/passwd

setup-2.5.58-7.el5.noarch : A set of system configuration and setup files.
Repo        : installed
Matched from:
Other       : Provides-match: /etc/passwd
如果有多個repos,就會有多比資料。provides也可提供套件的模糊搜尋。

清除(clean)

cache指的是rpm本身。yum從站台下載下來的rpm都會存在暫存資料夾下安裝,但是安裝成功後並不會幫你清除。

yum clean packages
可以清除的對象還有headers/metadata/dbcache等。你可以直接用一個all代表清除全部:
yum clean all
刪除某套件的cache

建立一個自己的repo

建立一個yum repo比想像中更容易,你只要把rpm放在一個指定的目錄下,就可以建立一個repo:

createrepo -v /path/to/rpmrepo
這個指令在於產生一個repodata的目錄,內含filelists.xml.gz這類重要的檔案。產生一個新的.repo把這個位置加進來,可以是local硬碟file://,也可以是ftp://,也可以是http://。

參考文章:
1. Redhat Enterprise Linux Administration Unleashed, Chapter 3.
2. YUM的使用-PHP5網管實驗室
3. 使用 yum 來做套件管理並建置 yum Server

2010年4月23日 星期五

rpm速記

rpm的基本安裝過程:
RPM(Redhat package Manager)是Redhat系的linux最必須要熟知的套件管理程式,許多非Redhat系的linux也沿用這個管理程式,例如SuSE Linux, Mandirva以及其衍生的PCLinuxOS等。rpm的功能非常完備,比起dpkg管理程式更勝一籌。
rpm的所有動作都會與rpmdb進行互動,也就是透過rpm所安裝的程式都能夠被記錄下來;手動安裝的程式則不在db內,因此也無法享受這方面的便利性。安裝、移除、升級rpm時都會更新rpmdb,但是仍然可以手動更新:

rpm --rebuilddb
rpm檔的命名遵循一定的格式:
Filename-version-release.arch.rpm
例如GConf2-2.14.0-9.el5.i386.rpm,其中的GConf2就是檔案名稱,2.14.0為版本號,9為釋出番號,el5.i386表示這是一個適用於RHEL5 x86平台的rpm檔。一個rpm的安裝會有下列過程:
  1. 檢查數位簽章
  2. 進行相依性檢查
  3. 執行pre script
  4. 複製檔案內容至指定位置
  5. 執行post script

GPG(GNU Private Guard) key數位簽章驗證

GPG key(或稱為signature key)是rpm的發行商應該提供的一個數位簽章(也就是一組公開金鑰)在安裝前rpm會進行檢查。如果rpm檔沒有數位簽章,或是rpmdb沒有紀錄該發行商的公鑰,則rpm數位簽章認證則會出錯:

rpm --checksig http://192.168.2.254/RHEL5/Server/GConf2-2.14.0-9.el5.i386.rpm
http://192.168.2.254/RHEL5/Server/GConf2-2.14.0-9.el5.i386.rpm: 
(SHA1) DSA sha1 md5 (GPG) NOT OK (MISSING KEYS: GPG#37017186)
假設我們想匯入GPG key到系統裡,應該用--import:
rpm --import http://192.168.2.254/RHEL5/RPM-GPG-KEY-redhat-release
我再試一次:
rpm --checksig http://192.168.2.254/RHEL5/Server/GConf2-2.14.0-9.el5.i386.rpm
http://192.168.2.254/RHEL5/Server/GConf2-2.14.0-9.el5.i386.rpm: 
(sha1) dsa sha1 md5 gpg OK
其中,--checksig可以用-K來代替。GPG key的簽章校驗失敗並不會讓安裝無法進行,只是rpm被包裹成類似cpio的格式,沒辦法輕易得知裡面的內容是否被有心人士更動過,因此匯入發行商的公開金鑰進行數位簽章的認證其實是常被忽略但極為重要的一個步驟。

安裝:

rpm -ivh foo.rpm
其中,-i表示install, -v為verbose,-h則是用50個#(hash marks)來顯示進度。如果你對debug rpm感興趣,你還可以用-vv顯示更詳盡的內容。
rpm -i --test foo.rpm
非常有趣的一種方式,利用--test測試安裝,過程並不會真的安裝,而是把-i之後的結果先印給使用者。如果結果符合預期,可以把--test拿掉進行真正的安裝。

升級:

rpm的升級可用兩種方式:

rpm -Uvh foo.rpm
-U表示Upgrade and install的意思。如果系統內已經有舊版本的套件,則會移除後再安裝新版本;如果沒有既有套件,則等同於-i全新安裝;這也是很多人常用-Uvh來安裝rpm的原因。
rpm -Fvh foo.rpm
-F為Freshen之意,意思比upgrade更像upgrade。使用-F,系統內必須已經安裝了較舊或相同版本的套件,她並不會像-U自動升級安裝。
需切記核心的升級要使用-i全新安裝,而不要使用-U/-F。原因是rpm -U會移除舊的kernel並安裝新的,但是我們並無法確定新核心是否有問題,甚至不確定能否正常開機。使用-i進行一個新的安裝,一旦新核心有問題,還可以開回舊核心繼續作業。

重新安裝:

rpm -ivh --replacepkgs foo.rpm
雖然名為replace,但是就是reinstall的意思。適用於相同版本號的套件。
rpm -ivh --replacefiles foo.rpm
如果既有檔案與foo.rpm會安裝到系統的檔案有重複或是套件間有conflict,則會覆蓋掉系統的舊檔案,也就是忽略套件間衝突
rpm -ivh --oldpackage foo.rpm
如果為了讓某些程式可以跑,需要舊一點的套件(最常見的就是舊版的gcc),你可能需要downgrade你的套件。利用--oldpackage指定一個比現有套件還舊的package來安裝。強制安裝一個rpm檔,完全忽略相依性未解決的問題。如果你根本不想理會到底是降級到舊版本或是覆蓋舊檔的問題,你可以用--force代替上面三個範例:
rpm -ivh --force foo.rpm
完全等同於
rpm -ivh --replacefiles --replacepkgs --oldpackage foo.rpm
不過這樣硬幹並非好事,而且還是沒辦法解決相依性的問題。如果你只想忽略相依性而強制安裝,應該用--nodeps:
rpm -ivh --nodeps foo.rpm
如果你是x86_64的機器,可是binaries只有for x86且沒有source code可供編譯,可以試試看安裝不同arch的rpm:
rpm -ivh --ignorearch foo.x86.rpm
如果你的硬碟空間非常有限,系統又跑的是你再熟悉不過的服務跟指令,你可以選擇不裝man pages:
rpm -ivh --excludedocs foo.rpm
如此一來雖然你可以執行一個命令,但是沒有他的man page。

移除:

rpm -e foo
不用接版本號就可以移除(erase)該套件。假設該套件同時安裝了x86及x86_64兩種版本,則只好辛苦一點,指定全名:
rpm -e foo-version-arch

查詢已安裝的rpm檔:

印出套件名稱及版本號:

rpm -q foo
如果要列出系統所安裝『所有』套件,則可用
rpm -qa
來觀察。不過-qa列出的資訊太過龐雜,因此較常見的用法是搭配grep搜尋關鍵字:
rpm -qa | egrep "*samba*"
當然,也可以利用-qa來列出系統已安裝的public key:
rpm -qa gpg-pubkey
如果知道套件名稱,想知道他的詳細訊息(info):
rpm -qi foo
如果想知道系統的某個檔案(file)是由哪個套件提供,可以使用-f:
rpm -qf /etc/passwd
反之,如果你想知道這個rpm究竟裝了哪些東西到你的系統(這恰好是windows最不希望使用者知道的...),可以讓rpm列表(list):
rpm -ql foo
不過,列出的訊息實在太多了,應該可以使用grep撈出有用的資訊,看看有哪些是doc,又有哪些是設定檔;你可以用-qd指查詢docs
rpm -qd foo
或是-qc來查看conf檔:
rpm -qc foo
或是進一步查看套件的相依性:
rpm -q --requires foo
這個指令應該反過來理解:foo套件(或指令)需要哪些套件(或檔案)。例如,python指令需要哪些套件或libs:
rpm -q --requires python
/bin/sh  
/usr/bin/env  
libbz2.so.1  
libc.so.6
...以下略  
相反的,查詢某套件提供了哪些指令或libs,例如,python提供了哪些套件跟libs:
rpm -q --provides python
Distutils  
_bisect.so  
_bsddb.so  
_codecs_cn.so
...中間略  
python = 2.4.3-27.el5
顯示python提供了Distutils套件等,也提供了python自己。
rpm -q --provides foo
跟上面相反:foo套件提供了哪些能力。例如:
rpm -q --provides passwd
config(passwd) = 0.73-1
passwd = 0.73-1
與--provides/--requires類似的兩個options分別是--whatprovides與--whatrequires。
rpm -q --whatprovides python
python-2.4.3-27.el5
rpm -q --whatprovides /etc/passwd
setup-2.5.58-7.el5
被查詢的對象可以是一個檔案,也可以是套件本身。python由python-2.4.3-27.el5提供而來,/etc/passwd則由setup-2.5.58-7.el5而來。
rpm -q --whatrequires bash
info-4.8-14.el5
gpm-1.20.1-74.1
initscripts-8.45.30-2.el5
ypbind-1.19-12.el5
sysklogd-1.4.1-46.el5
vixie-cron-4.1-77.el5_4.1
sendmail-8.13.8-8.el5
squid-2.6.STABLE21-6.el5
vnc-server-4.1.2-14.el5_3.1
bash套件被這些套件所依賴。
rpm -q --whatrequires `which bash`
bash-3.2-24.el5
iproute-2.6.18-11.el5
gpm-1.20.1-74.1
groff-1.18.1.1-11.1
iputils-20020927-46.el5
xorg-x11-filesystem-7.1-2.fc6
crontabs-1.10-8
...族繁不及備載
/bin/bash這個檔案被更多的套件所依賴,不難想像linux就是一個大量shell script架構出來的系統。透過--provides/--whatprovides/--requires/--whatrequires這四個參數就可以把rpm的相依性完全釐清,只是在使用--what參數時總是容易令人混淆。 甚至你也可以檢查這個套件在安裝時的狀態(status):
rpm -qs foo

查詢一個rpm檔:

很幸運的,剛剛我們所列出的options都還可以繼續沿用,要查詢一個rpm檔而不是已經安裝的套件名稱,只需要多加一個-p即可。例如查詢一個rpm的info:

rpm -qpi foo.rpm
想知道這個rpm究竟包含哪些binaries以及libraries:
rpm -qp --provides foo.rpm
以及她需要哪些套件或libs:
rpm -qp --requires foo.rpm
甚至你可以清楚的查看安裝這個rpm的blockquote script以及post script:
rpm -qp --script foo.rpm
在安裝前就先看看這個rpm會裝哪些東西到系統裡:
rpm -qpl foo.rpm
當然還是可以搭配--what,只是別忘了記得加-p

patch檔的查詢:

很多時候我們會下載一個小的patch檔而非一整個全新的rpm,要查看這個rpm patch會更新哪些檔案只需要多一個-P:

rpm -qPpl foo.patch.rpm
有了先前的經驗,我們也可以知道某patch套件更新了哪些檔案:
rpm -qPl foo
當然,你更可以查詢整個系統所有被patch過的檔案有哪些:
rpm -qaP

稽核(Verifying)rpm檔;

稽核rpm檔是比較rpm安裝在檔案系統內的檔案與rpmdb所紀錄的檔案資訊做比較。比對的項目有八項:

  1. file size
  2. 檔案大小是否改變 (S)
  3. file type
  4. 檔案狀態(權限、類型)是否被改變 (M)
  5. MD5 checksum
  6. 以md5sum指令進行計算 (5)
  7. device
  8. 裝置檔是否改變 (D)
  9. linkage
  10. 是否指向另一檔案 (L)
  11. owner
  12. user是否改變 (U)
  13. group
  14. group是否改變 (G)
  15. mtime
  16. 修改時間 (T)
例如,檢查vim套件有哪些檔案被修改過:
rpm -V vim-common
S.5....T  c /etc/vimrc
校驗rpm的結果用上述八個欄位表示,上面的結果表示vimrc在安裝之後大小改變,因此md5 checksum也必定改變,修改時間也改變了。"."表示從未改變。假設這個檔案被移除了,則會顯示missing;如果你是用一般使用者的身份查詢系統檔案,很可能因為權限不足而產生"?"的狀態,請切至root執行rpm -V即可正常檢查。

解開rpm:rpm2cpio

rpm2cpio能解一個rpm檔導入cpio解開成檔案。利用上面所學檢查系統是否有rpm2cpio這個程式:

rpm -qf `which rpm2cpio`
可見這個指令就是包含在rpm套件裡面。
rpm2cpio foo.rpm | cpio -idmv
其中,-i表示解開一個cpio檔,-d建立目錄樹(man pages上說cpio只會解檔案不解目錄,但我測試結果,加不加-d是相同效果),-m使還原後能保留mtime,-v為詳細輸出。
如果只是要查看rpm內容,可以不需要輸出:
rpm2cpio foo.rpm | cpio -vt

參考文獻:
1. Redhat Linux網路及系統管理指南(學貫),第26章
2. 鳥哥的私房菜第23章
3. How To Extract an RPM Package Without Installing It.

2010年4月9日 星期五

批次修改圖片大小-convert

最近在BBS上看到有網友詢問如何利用convert指令做批次轉換。在先前的批次修改圖片大小裡有提到一些方法。不過當時我一直忘記把script寫上來,今天特地補上。

#!/bin/bash

for files in *.ps; do
    name=$(echo $files | cut -d. -f1).pdf
    convert $files $name
done

這個作法的好處就是只要修改.ps跟.pdf這兩個關鍵字即可。當然他不是一個完美script-- 你還可以讓他變得更人性:

#!/bin/bash
## Author: Jim T. Tang (http://maxubuntu.blogspot.com)
if [ -z $1 -a -z $2 ]; then
    echo "usage: $0 jpg png";
    exit 0;
elif [ -z $2 ]; then
    echo "need target format. e.g. ps"
else
    for files in *.$1 ; do
        name=$(echo $files | cut -d. -f1).$2
        convert $files $name
        echo "$name is made."
    done
fi