使用預編譯的 RPM 以及從源代碼編譯應用程序
Chris Walden
電子商務架構師, IBM Developer Relations
2004 年 1 月
IBM 電子商務架構師 Chris Walden 將通過他在 developerWorks 上發表的九篇系列文章來指導您如何在 Linux 環境中運用您的 Windows 操作技巧。在這最后一部分中,我們將下載和編譯一個軟件包,討論自動化包管理的優點和缺點,同時了解 RPM 系統。
安裝 Linux 時首先注意到的事情之一,就是 Linux 發行版本中有如此多可用的包。大多數發行版本都附帶了 Linux 操作系統、安裝工具和管理工具。它們還包括 Internet 工具、開發工具、辦公工具、游戲,以及一些您不曾聽說過的程序。Linux 發行版本附帶 數千個可用包的情況并不鮮見。如果您沒有選擇“完整安裝”,則只會安裝這些包的一個子集。
現在您可能想知道“如何刪除不想要的包?如何安裝遺漏了的包?是否能夠使用不是該發行版本附帶的軟件?”
RPM
在安裝 Linux 時,您或許會注意到關于正在安裝的 RPM 的許多信息。 RPM 代表 Redhat Package Manager(Redhat 包管理器),這是 Redhat 的貢獻,現在已成為管理 Redhat 和 UnitedLinux 以及其他許多發行版本上的軟件的標準。
RPM 本質上就是一個包,包含可以立即在特定機器體系結構上安裝和運行的 Linux 軟件。例如,在“ 第 3 部分. Webmin 簡介”中,我們通過一個 RPM 安裝了 Webmin 包。最初加載到發行版本中的所有軟件都是通過一個 RPM 來安裝的。
RPM 剖析
RPM 是文件包。它包括的 .spec 文件提供了關于包及其功能和依賴關系(即在該包能夠運行之前必須安裝其他哪些包)的信息。.spec 還包含包中的文件清單,指定這些文件必須加載到系統中的何處,以及它們的初始權限如何。RPM 還包含安裝前腳本,這是由包開發人員編寫的。RPM 其次還包含已編譯的二進制文件。最后,RPM 包含了安裝后腳本。
RPM 結構
.spec |
安裝前腳本 |
二進制文件 |
二進制文件 |
... |
二進制文件 |
安裝后腳本 |
在安裝 RPM 時,系統首先檢查該包的依賴關系是否得到滿足。如果不滿足, 安裝過程就會終止,除非您指定了迫使安裝無論如何都要繼續的選項。
如果一切順利,安裝前腳本就會運行。這個腳本可以做任何事情。它通常創建用戶和目錄。然而,它可以做許多類型的動態配置,甚至以自定義的方式編譯運行系統的源代碼。
了解 RPM 來自何處 RPM 在安裝時將文件復制到您的系統上,并執行腳本。由于 RPM 是以 root 身份運行的,因此所有這些功能都以 root 身份執行。因而在將某個 RPM 安裝到系統之前,知道它的由來是很重要的。就像許多 Windows 軟件一樣,惡意的代碼可以像包含在其他包中一樣容易地包含在 RPM 中。來自廠商的 RPM 一般都是安全的,但是要對從未知來源隨機下載和安裝的內容保持警惕。 |
如果安裝前腳本成功完成,二進制文件將依照清單被復制到系統上。在復制完所有的文件和設置了它們的權限之后,安裝后腳本就會運行。同樣,這個腳本幾乎能夠做任何事情。
一旦完成所有這些步驟,關于包的信息就被添加到 RPM 數據庫,安裝過程就完成了。使用這種簡單的機制,您能夠執行通過更完善的商業安裝程序所能執行的所有功能。
RPM 數據庫
RPM 的優雅之處是 RPM 數據庫。這個數據庫通常位于 /var/lib/rpm 目錄,它包含關于系統上已安裝的每個 RPM 的信息。這個數據庫知道包之間的依賴關系,當刪除某個包將導致其他包無法工作時,它將發出警告。這個數據庫知道最初隨某個包安裝的每個文件以及這些文件在系統上的最初狀態。它還知道每個包的文檔和配置文件的位置。這聽起來好像是大量的信息,事實上確實如此。但它并不是過多而龐大的。在一個包含 1,066 個包、由 203,272 個文件組成的系統上,數據庫文件僅有 45 MB!在加載和卸載包時,RPM 使用這個數據庫來檢查依賴關系。用戶還可以在這個數據庫中查詢關于包的信息。
使用 RPM
配合 RPM 包使用的程序被相應地命名為 rpm
。 rpm
以多種不同的模式運行,不過最常見的任務是安裝、升級、查詢、驗證和刪除。
rpm -i (裝)
在第一次安裝某個包時,您要使用 -i
或安裝模式。只需將 rpm 指向某個二進制包并執行它, rpm 就會把該包安裝到您的系統上。安裝過程一般只需幾秒鐘。我經常會在安裝包時使用 -v
(詳細)開關來提供關于該過程的更多信息,以及使用 -h
(哈希線)開關來通過輸出在控制臺上的哈希(#)符號提供安裝進度更新。下面是安裝某個包的例子:
清單 1. 安裝 MyPackage
$ rpm -ivh MyPackage-1.0.0.i386.rpm
Preparing... ########################################### [100%]
1:MyPackage ########################################### [100%]
|
就是這個樣子!MyPackage 現在已經安裝完成,可供使用了。
rpm -e (刪除)
要刪除已安裝的包,可使用 -e
開關。 rpm
將使用數據庫來刪除該包的所有文件。如果有已安裝的其他包依賴正在刪除的包, rpm
將會異常退出。您必須使用 nodeps
開關來執行強制刪除( nodeps
還可以用于強制安裝)。在使用這個開關來強制安裝或刪除時,務必 非常 小心。刪除其他包所依賴的包,可能會導致災難性的結果。下面這個命令刪除我們在上面安裝的包:
注意,包的刪除并不一定需要它的完整名稱(包括版本號)。安裝時需要完整名稱,因為我們是在引用一個文件名稱。已安裝的包僅通過它們的名稱來引用。包的名稱是版本號之前的所有內容。
rpm -V(驗證)
驗證開關非常有用。它將包文件的當前狀態與它們在安裝時的原始狀態作比較。兩種狀態之間的區別將用一個代碼來顯示:
文件驗證結果
S |
文件大小不一致 |
M |
模式不一致(包括權限和文件類型) |
5 |
MD5 校驗和不一致 |
D |
設備主要/次要編號不匹配 |
L |
readLink(2) 路徑不匹配 |
U |
用戶擁有關系不一致 |
G |
群組擁有關系不一致 |
T |
mTime 不一致 |
如果您對某個包運行 rpm -V
,并且發現某個可執行文件的大小發生了變化,那可能就是安全漏洞的征兆。
rpm -U(升級)
一旦某個包已經安裝,嘗試安裝具有相同名稱的包將產生一條消息,指出該包已經安裝。 如果想要將某個包升級到更新的版本,可使用 -U
開關來升級。升級還具有另一個影響。當對多個包名稱運行升級時,它將設法按依賴關系的順序放置包。換句話說,必需的包將首先安裝。不管某個包是否已經安裝,都可以對它使用升級開關,許多人使用它而不是使用 -i
開關來執行安裝和升級。下面是使用升級開關來加載多個 rpm 包的例子:
清單 2. 交互式升級
$ rpm -Uvh My*.rpm
Preparing... ########################################### [100%]
1:bMyPackageDep ########################################### [ 50%]
1:aMyPackageNew ########################################### [100%]
|
在上面的例子中,bMyPackageDep 是 aMyPackageNew 的前提條件,因此盡管文件名稱以相反的順序排列, rpm
也會對它們正確排序。
rpm -q(查詢)
可以從 rpm 數據庫中查詢多種有用的信息。對 rpm 數據庫擁有讀訪問權限的任何用戶都能夠運行查詢。默認情況下,全部用戶都擁有讀訪問權限。要運行一個查詢,可使用 -q
開關帶上要查詢的包的名稱。這樣將返回該包的版本。
$ rpm -q MyPackage
MyPackage-1.0.0
|
包的名稱必須精確匹配,不允許使用通配符。然而,如果記不住包的完整名稱,您可以使用 grep
工具來幫助找到它。可以使用 -qa
開關來查詢所有已安裝的包,并用 grep
來管道輸出您能記住的信息。例如:
grep 之樂
grep 是一個具有廣泛用途的文本搜索工具。默認情況下, grep 將搜索文件以顯示您指定的行。在這里的例子中,它搜索單詞“IBM”。 grep 是腳本編寫和控制臺工作方面的一個強大工具。 |
$ rpm -qa | grep IBM
IBMWSAppDev-Product-5.0-0
IBMWSSiteDevExp-Core-5.0-0
IBMWSSiteDev-Core-5.0-0
IBMWSTools-WAS-BASE-V5-5.0-0
IBMJava118-SDK-1.1.8-5.0
IBMWSWB-samples-5.0-0
IBMWSWB-5.0-0
IBMWSAppDev-Core-5.0-0
IBMWSAppDev-5.0-0
IBMWSTools-5.0-0
|
除了版本號外, rpm -q
還可以提供關于包的其他有用信息。下面就是這樣一些例子:
使用 rpm 查詢獲取信息
rpm -q changelog |
顯示包的開發變更歷史記錄 |
rpm -qc |
顯示包的配置文件 |
rpm -qd |
顯示包的文檔文件 |
rpm -qi |
顯示包描述 |
rpm -ql |
顯示包的文件的列表 |
rpm -qR |
顯示包的依賴關系 |
還有另一個有趣的查詢命令,它針對文件而不是針對包運行。
rpm -q whatprovides <filename>
|
上面這個命令將識別與給定的 filename(文件名)相關聯的包。filename 必須包括文件的絕對路徑,因為信息就是以這種方式存儲在 rpm 數據庫中的。
RPM 前端
從控制臺操作 rpm
很容易,但有時使用圖形用戶界面會更方便。在典型的 Linux 風格中,有一些前端程序為 rpm 程序提供界面。每種發行版本都有一個前端,但是它們各不相同。請參考您的發行版本文擋,以了解關于所提供的包管理工具的信息。
Webmin 軟件包
Webmin 也為處理 RPM 包提供了一個基于 Web 的簡單前端。
圖 1. Webmin RPM 界面
軟件可以從這個界面容易地安裝、刪除和查詢。還可以直接從 URL 站點安裝軟件。如果安裝了諸如 apt
或 Redhat Network 之類的 rpm 增強工具,Webmin 將識別它們并為它們提供一個界面。
源代碼
由于 Linux 是開放源代碼的操作系統,它附帶了編譯軟件所需的所有開發工具。雖然您使用的大多數包將以二進制 RPM 的形式提供,但是您并不僅限于使用那些包。如果愿意,您可以為您的系統下載原始源代碼,并以自定義的方式進行編譯。
應該對在生產系統上編譯源代碼保持謹慎,因為這樣可能導致問題,或者不再支持系統上正在使用的商業軟件(比如 IBM DB2)。然而,熟悉從源代碼編譯軟件的過程將使您能夠對軟件應用補丁,以及使用從其他環境移植過來的包。一旦成功地編譯代碼,創建您自己的 RPM 也是可以做到的!
Corewars 源代碼演示
為演示從源代碼編譯軟件有多簡單,我們將編譯一個名為 Corewars 的模擬游戲(請參閱 參考資料)。下面是來自他們 Web 站點的關于 Corewars 的說明:“Corewars 是一款模擬游戲,其中許多武士在虛擬的計算機中奔跑時竭力相互攻擊對方。可以采用兩種類似匯編程序的語言中的一種來編寫武士程序,這兩種語言分別叫做 Corewars 和 Redcode。Corewars 是默認語言,更易于學習和理解。Redcode 提供更高級和更強大的指令,但是需要更多的時間來學習。”
編譯源代碼的第一步是從 Web 站點下載源代碼包:
在代碼下載完成之后,需要展開這個包。
tar -xvzf corewars-0.9.13.tar.gz
|
文件將展開到當前目錄。標準的做法是將源代碼包含在一個與產品名稱匹配的目錄中。在此例中,源代碼位于一個名為 corewars-0.9.13 的目錄。
首先進入該目錄,找到源代碼和一些文檔、配置腳本和 README 文件。大多數源代碼包都帶有一個名為 INSTALL 和一個名為 README 的文件。您應該在編譯軟件之前首先閱讀這些材料。它們在問題出現之前識別問題,并為您建議正確的編譯和安裝步驟,這樣通常可以讓您少走許多彎路。我在編譯源代碼時遇到的大多數問題都是因為我沒有遵循那些指導。
通常執行的下一步是運行 configure
腳本。 configure
是 Autoconf 包的一部分,包括在 Linux 發行版本的開發工具中。這里引用一段 Autoconf 的包描述:“GNU 的 Autoconf 是一個用于配置源代碼和 Makefile 的工具。通過使用 Autoconf,程序員能夠創建可移植和可配置的包,因為建立包的人可以指定各種配置選項。”
configure
腳本在系統上運行一系列測試,以確定為您的發行版本和系統體系結構編譯包的最佳方式。然后它為您的系統創建一個定制的 Makefile。如果在您的系統上編譯時遇到問題, configure
將會告訴您。 configure
通常允許您自定義將要在編譯中包括的特性,或允許您提供關于庫或者其他必需文件的位置參數,以便能夠成功地編譯包。下面我們將不帶參數執行 configure
:
在系統上多執行幾次測試,最終就會編譯成功。下面使用如下命令來生成程序:
如果編譯有錯誤,就需要確定問題并修復它們。這可能是一件繁瑣的任務,也許需要關于環境和程序設計的大量一般知識。如果一切順利,我們一般會使用以下命令來安裝軟件:
文件將被復制到系統中的正確位置,文件權限會被更新,配置文件將被復制,文檔也會被添加到手冊頁。
現在通過執行該程序來測試我們的勞動成果。它是一個圖形化的程序,因此要在啟動它前運行 X 系統。上面執行的 make install
命令應該已將程序放到了可執行文件路徑中。
作為對我們的獎賞,一個圖形化的屏幕應該會出現。
圖 2. 大功告成!
corewars 規則的主題超出了本文的討論范圍,不過您會在手冊頁( man corewars
)中找到關于這款有趣的模擬游戲的文檔。
corewars 的編譯是一個典型的場景。可能會有其他許多種變化形式,包括在 configure
腳本上使用開關來調整要編譯到程序中的特性,以及從 Makefile 使用不同的命令來調整編譯方式,等等。
由于這個程序不是使用 rpm 來安裝的,因此 rpm 數據庫中沒有相應的條目。如果某個程序在安裝后沒有按預期運行,大多數 Makefile 都包括了一個卸載參數來刪除軟件:
務必牢記,使用原始源代碼不會在 RPM 數據庫中添加任何內容。以這種方式安裝的軟件是非托管的(unmanaged),因此應該小心進行。
源代碼 RPM
當 RPM 被創建時,還有一個稱作源代碼 RPM 的產物。這是一個與源代碼組合在一起的 SPEC 文件,設計它的目的是為了在一個或多個體系結構上生成程序。這對源代碼和二進制這兩個世界來說是最佳的!對于源代碼 RPM,您可以在系統上定制編譯軟件,但是完成的產品將是一個可安裝的 RPM,而不是原始的二進制。以預編譯 RPM 的形式可用的大多數包還以 SRPM 的形式可用。這也許是在 Linux 中軟件跨平臺轉移的簡單途徑。當您在一個不同的平臺上成功地重新編譯時,可考慮與整個開發社區共享完成的 RPM。
也許源代碼更適合您
如果您是 Linux 新手,安裝軟件的方法與您過去習慣使用的方法不同。然而,RPM 安裝方法是優雅的,同時提供了您很快就會欣賞的新能力。
您應該熟悉從控制臺使用 rpm 的選項,不過對于日常使用,有一些前端界面選項使得 rpm 更易于管理。您的發行版本提供了這樣一個界面,也有其他類似的界面可供使用,比如 Webmin 中的那一個界面。
您并不僅限于使用預編譯的 rpm,還可以利用 Linux 的開放源代碼性質,直接從源代碼編譯應用程序。對于成熟的項目,編譯通常是很容易的。記住,從源代碼安裝的代碼在 rpm 數據庫中沒有相應的條目。在使用源代碼時,可考慮使用源代碼 rpm,它組合了已編譯源代碼的強大能力和 rpm 的可管理性。
參考資料
關于作者 Chris Walden 是位于德克薩斯州奧斯汀的 IBM Developer Relations Technical Consulting(也稱為 dragonslayers )的一名電子商務架構師,該公司為 IBM 商業伙伴提供教育、實現和咨詢。他致力于 Linux 相關工作,一有機會就向身邊的人宣傳 Linux 的種種好處。除了完成他的架構師的職責之外,他還精通 Linux 基礎設施服務器的各個領域,包括混合平臺用戶環境下的文件、打印以及其他應用服務等。Chris 有 10 年的計算機行業經驗,從現場支持到 Web 應用開發和顧問,各個領域他都曾涉足。您可以通過 cmwalden@us.ibm.com 與 Chris 聯系。 |
posted on 2005-10-27 09:31
小強 閱讀(253)
評論(0) 編輯 收藏 所屬分類:
Linux