無論是初步跨入Linux殿堂的新手,仍是具備多年經驗的專家,在安裝或編譯軟件包的過程當中或多或少的都會遇到包的依賴問題,從而致使安裝過程沒法繼續,好比管理員在安裝LAMP時,包須要libgd.so文件,而這個文件屬於GD軟件包。可是在安裝GD軟件包時,可能這個軟件包跟其餘軟件包又具備依賴關係,又須要安裝其餘軟件包才行。這時有的管理員便失去耐心。在遇到這種Linux軟件包依賴關係問題時,該如何解決呢?在談這個具體的措施以前,先跟你們聊聊Linux系統裏的軟件依賴性問題。
1、什麼是依賴性
程序依賴於程序代碼的共享庫,以便它們能夠發出系統調用將輸出發送到設備或打開文件等(共享庫存在於許多方面,而不僅侷限於系統調用)。沒有共享庫,每次程序員開發一個新的程序,每一個程序員都須要從頭開始重寫這些基本的系統操做。當編譯程序時,程序員將他的代碼連接到這些庫。若是連接是靜態的,編譯後的共享庫對象代碼就添加到程序執行文件中;若是是動態的,編譯後的共享庫對象代碼只在運行時須要它時由程序員加載。動態可執行文件依賴於正確的共享庫或共享對象來進行操做。rpm依賴性嘗試在安裝時強制實施動態可執行文件的共享對象需求,以便在之後當程序運行時不會有與動態連接過程有關的任何問題。
注意:還有一種類型的依賴性,它基於顯式的條目,rpm經過程序員將該依賴性強加到rpm配置文件中,但目前咱們不關心這種類型的依賴性,這種依賴性比較容易解決。這裏將重點放在rpm強制實施的更加複雜的共享對象依賴性。
2、動態可執行文件和共享對象
動態可執行文件使用最初編譯和連接程序時使用的庫文件的共享對象名稱來查找共享對象。它們在少數的幾個標準位置查找,好比在/lib和/usr/lib目錄及在LD_LIBRARY_PATH環境變量(主要用於指定查找共享庫,好比咱們在安裝Oracle時指定路徑,export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib:/usr/local/lib)指定的目錄中。順便提一下,在這些庫目錄中找到的共享對象可能不是真正的文件;它們多是指向位於其餘位置的真實庫文件的符號連接(但一般仍舊在標準庫目錄的一個目錄中)。至少從系統管理員的觀點是在用於建立共享庫文件的共享庫軟件包的名稱和共享庫文件的名稱之間一般沒有什麼關係。例如,GLIBC 2.3軟件包用於建立libc.so.6共享庫文件。也從本示例中注意到,添加到共享庫文件名結束的版本號(.6)跟用於建立它的版本號(2.3)沒有關係。這是由共享庫軟件包開發人員有意完成的,以便GLIBC的新版本能夠重用相同的共享庫文件名libc.so.6。這容許您在系統上加載新版本的GLIBC,而不用中斷動態連接到lib.so.6共享庫文件的全部程序,固然假定新版本的GLIBC向後與動態可執行文件最初所連接的老版本GLIBC兼容。所以,即便庫文件或共享對象文件有與它們相關的版本號,這些版本號也不能幫助你肯定他們來自哪一個版本的共享軟件包。
注意:當將whatprovides選項用於rpm查詢命令時,能夠得到有關使用rpm軟件包加載到系統的現有共享對象的信息。這種混亂是由下面的事實形成的:單個共享庫文件可能支持某個範圍的共享庫軟件包版本。例如,要檢查soname庫文件/lib/libc.so.6支持的GLIBC共享庫軟件包,運行下面的命令:
#objdump --all-headers /lib/libc.so.6 | less
向下滾動此報告,直到到達Version definitions: 部分,以便查看libc.so.6共享庫文件支持哪些GLIBC版本:
Version definitions:
1 0x01 0x0865f4e6 libc.so.6
2 0x00 0x0d696910 GLIBC_2.0
3 0x00 0x0d696911 GLIBC_2.1
GLIBC_2.0
4 0x00 0x09691f71 GLIBC_2.1.1
GLIBC_2.1
5 0x00 0x09691f72 GLIBC_2.1.2
GLIBC_2.1.1
6 0x00 0x09691f73 GLIBC_2.1.3
GLIBC_2.1.2
7 0x00 0x0d696912 GLIBC_2.2
GLIBC_2.1.3
8 0x00 0x09691a71 GLIBC_2.2.1
GLIBC_2.2
9 0x00 0x09691a72 GLIBC_2.2.2
GLIBC_2.2.1
10 0x00 0x09691a73 GLIBC_2.2.3
GLIBC_2.2.2
11 0x00 0x09691a74 GLIBC_2.2.4
GLIBC_2.2.3
12 0x00 0x09691a76 GLIBC_2.2.6
GLIBC_2.2.4
13 0x00 0x0d696913 GLIBC_2.3
GLIBC_2.2.6
14 0x00 0x09691972 GLIBC_2.3.2
GLIBC_2.3
15 0x00 0x09691973 GLIBC_2.3.3
GLIBC_2.3.2
16 0x00 0x09691974 GLIBC_2.3.4
GLIBC_2.3.3
17 0x00 0x0d696914 GLIBC_2.4
GLIBC_2.3.4
18 0x00 0x0d696915 GLIBC_2.5
GLIBC_2.4
19 0x00 0x0963cf85 GLIBC_PRIVATE
GLIBC_2.5
20 0x00 0x0b792650 GCC_3.0
在本示例中,1ibc.so.6共享庫文件支持原先爲GLIBC版本2.0到2.5而開發的全部動態執行文件。注意:也可使用objdump命令來從共享庫文件中提取soname,命令以下所示:
# objdump --all -headers /lib/libcrypto.so.0.9.8b| grep SONAME
SONAME libcrypto.so.6
objdump: /lib/libcrypto.so.0.9.8b: no recognized debugging information
接下來,將討論rpm軟件包是如何生成的,以便在新系統上安裝rpm軟件包時,這些共庫依賴性是己知的。
3、Rpm軟件包和共享庫依賴性
當程序員生成rpm軟件包時,ldd命令用於報告動態可執行文件軟件包中全部動態可執行文件使用的全部共享庫。另外一個混亂是由下面的事實帶來的:相同軟件包中的不一樣動態可執行文件可能與相同的共享庫軟件包的不一樣版本進行連接。例如,Heartbeat軟件包中的不一樣程序可能已經進行了開發,並動態連接到libc.so.6 sonmae共享庫文件的不一樣GLIBC版本。對rpm命令使用-q和--requires參數,能夠看到rpm軟件包須要的共享庫的完整清單。例如,要看到Heartbeat rpm軟件包全部的所需依賴性,請使用命令:
#rpm -q --requires -p heartbeat-1.x.x.i386.rpm
這產生了下面的報告:
sysklogd
/bin/sh
/bin/sh
/usr/bin/python
ld-linux.so.2
libapphb.so.0
libc.so.6
libc.so.6(GLIBC_2.0)
libc.so.6(GLIBC_2.1)
libc.so.6(GLIBC_2.1.3)
libc.so.6(GLIBC_2.2)
libc.so.6(GLIBC_2.3)
libccmclient.so.0
libdl.so.2
libglib-1.2.so.0
libhbclient.so.0
libpils.so.0
libplumb.so.0
libpthread.so.0
librt.so.1
libstonith.so.0
注意,在此報告中,libc.so.6 soname是所須要的,此共享庫必須支持使用GLIBC共享軟件包版本號2.0、2.一、2.1.三、2.2和2.3進行連接的動態可執行文件。這是由下面的事實決定的:Heartbeat軟件包中的不一樣動態可執行文件是針對不一樣版本的libc.so.6庫的每一個版本進行連接的。在瞭解了動態可執行文件、共享對象、soname和共享庫軟件包彼此是如何相關的後,下面準備來看這樣的一個例子:當嘗試安裝rpm軟件包,而且它因爲依賴性錯誤而失敗時,會發生什麼。yum可以從指定的服務器自動下載RPM包而且安裝,能夠自動處理依賴性關係,而且一次安裝全部依賴的軟體包,無須繁瑣地一次次下載、安裝。
4、手工解決依賴性問題
一般,當嘗試安裝發行版中沒有包括的軟件包(及不能由像up2date、apt- get或Yum同樣的更新工具自動解決其依賴性的軟件包)時,將碰到rpm依賴性錯誤。例如,若是嘗試在老的Linux發行版上使用rpm –ivh *rpm命令,例如全部的Heartbeat rpm包,那麼在安裝過程當中就可能碰到下面的錯誤:
error: failed dependencies:
libc.so.6(GLIBC_2.3) is needed by heartbeat-1.x.x
libc.so.6(GLIBC_2.3) is needed by heartbeat-pils-1.x.x
libcrypto.so.0.9.6 is needed by heartbeat-stonith-1.x.x
libsnmp-0.4.2.6.so is needed by heartbeat-stonith-1.x.x
注意,rpm命令沒有干擾報告所需的每一個GLIBC共享庫軟件包版本號——它只報告所需的最高編號的版本號(GLIBC_2.3)。(假定原來的軟件包開發人員不會將相同軟件包中的可執行文件連接到不兼容版本的共享庫軟件包)全部的這些故障都報告所需的共享庫名稱或soname(而不是文件名稱,soname始終以「lib」開始)。但能夠刪除添加到rpm報告的soname結束的版本號,並快速檢查以查看是否在系統中使用locate命令安裝這些共享庫(假設您的locate數據庫是最新的,有關更多信息,請參閱locate或slocate的手冊頁)。例如,要查找libcrypto享庫文件,要輸入:
#locate libcrypto
[root@localhost ~]# locate libcrypto
/lib/libcrypto.so.0.9.8b
/lib/libcrypto.so.6
/root/.Trash/vmware-tools-distrib/lib/lib32/libcrypto.so.0.9.8
/root/.Trash/vmware-tools-distrib/lib/lib32/libcrypto.so.0.9.8/libcrypto.so.0.9.8
/root/.Trash/vmware-tools-distrib/lib/lib64/libcrypto.so.0.9.8
/root/.Trash/vmware-tools-distrib/lib/lib64/libcrypto.so.0.9.8/libcrypto.so.0.9.8
/usr/lib/libcrypto.a
/usr/lib/libcrypto.so
/usr/lib/pkgconfig/libcrypto.pc
/usr/lib/vmware-tools/lib32/libcrypto.so.0.9.8
/usr/lib/vmware-tools/lib32/libcrypto.so.0.9.8/libcrypto.so.0.9.8
/usr/lib/vmware-tools/lib64/libcrypto.so.0.9.8
/usr/lib/vmware-tools/lib64/libcrypto.so.0.9.8/libcrypto.so.0.9.8
若是此命令沒有在系統上找到一個libcrypto共享庫文件,將須要轉到Internet並找出哪一個共享庫軟件包包含此共享庫文件。完成此項工具的一個快速和簡便方式是隻要在http://rpmfind.net上將共享庫的名稱輸入到搜索欄中。若是將文本libcrypto.so輸入到此搜索貞中,將很快知道此共享庫是由openssl軟件包提供的。
若是老版本的共享庫數據包已經安裝在系統上,能夠用以下的命令確認此軟件包含您須要的共享庫文件:
#rpm -q --provides openssl
[root@localhost ~]# rpm -q --provides openssl
config(openssl) = 0.9.8b-10.el5
lib4758cca.so
libaep.so
libatalla.so
libchil.so
libcrypto.so.6
libcswift.so
libgmp.so
libnuron.so
libssl.so.6
libsureware.so
libubsec.so
openssl = 0.9.8b-10.el5
此命令報告此rpm軟件包中提供的全部內容(這包括軟件包提供的共享庫文件的soname)。注意:如前面指出的,共享庫軟件包版本號沒有而且應該沒有與共享庫文件( soname)版本號的任何對應關係。這裏不進行這方面的討論,由於soname符號連接可能指向不一樣版本的共享庫文件,這也是在儘可能避免在安裝新版本的共享軟件包時中斷現有動態可執行文件的狀況下完成的。
5、自動解決依賴性故障
當您使用rpm軟件包來生成、升級或添加新的特性到系統時,依賴性故障可能很快變成一場惡夢。只要經過使用您的發行版供應商的升級服務或工具,就能夠避免這場惡夢。例如,當選擇要安裝的rpm軟件包時,Red Hat工具up2date自動從Red Hat下載並安裝全部rpm依賴性。下面就點上列出了幾個完成相同事情的支持社區的免費方法:http://www.rpm.org/。下面將只進一步看到這些自動更新工具中的一種:Yum。
1.使用Yum來安裝rpm軟件包
Yum(Yellow dog Updater,Modified)程序可從下面網址下載:http://yum.baseurl.org/download/3.4/yum-3.4.3.tar.gz
在下載了此軟件包後,可使用下面的命令像任何其餘rpm軟件包那樣安裝它:
#rpm -ivh yum*
您可能須要更新想用於下載您的rpm軟件包的存儲庫。有關Fedora的可用Yum存儲庫的清單在http://www.fedoratracker.org要切換到不一樣的存儲庫,下載這些文件中的一個文件,並將該文件做爲/etc/yum.conf文件安裝。如今能夠用下面的命令告訴Yum報告存儲在Yum存儲庫中、可用於安裝全部軟件包:
#yum list
[root@localhost ~]# yum list |more
This system is not registered with RHN.
RHN support will be disabled.
Loading "security" plugin
Loading "rhnplugin" plugin
Installed Packages
Deployment_Guide-en-US.noarch 5.2-9 installed
Deployment_Guide-zh-CN.noarch 5.2-9 installed
Deployment_Guide-zh-TW.noarch 5.2-9 installed
GConf2.i386 2.14.0-9.el5 installed
GConf2-devel.i386 2.14.0-9.el5 installed
ImageMagick.i386 6.2.8.0-4.el5_1.1 installed
MAKEDEV.i386 3.23-1.2 installed
MySQL-python.i386 1.2.1-1 installed
NetworkManager.i386 1:0.6.4-8.el5 installed
NetworkManager-glib.i386 1:0.6.4-8.el5 installed
2.用Yum安裝新的rpm軟件包
在本示例中,將安裝新的GLIBC軟件包。用簡單的命令安裝最新的GLIBC及其全部依賴性:
#yum update glibc
若是一切正常,Yum程序將自動檢測、下載並安裝最新GLIBC軟件包所須要的全部rpm軟件包(這裏的GLIBC軟件包是爲您的發行版而構建的,不必定是可用的最新版GLIBC軟件包(使用發行版所批准的GLIBC共享庫軟件包版本號或冒險安裝沒有使用正常系統操做所須要的動態可執行文件的GLIBC軟件包版本)。也能夠將list參數用於Yum和grep命令來查找要安裝的軟件包。例如,要查找名稱中有SNMP的軟件包,請輸入:
# yum list |grep snmp
此命令返回以下報告:
This system is not registered with RHN.
RHN support will be disabled.
net-snmp.i386 1:5.3.1-24.el5 installed
net-snmp-libs.i386 1:5.3.1-24.el5 installed
net-snmp-perl.i386 1:5.3.1-24.el5 installed
net-snmp-utils.i386 1:5.3.1-24.el5 installed
如今能夠容易地使用YUM下載並安裝全部這些rpm軟件包。
6、關於升級Gilbc的建議
Glibc 庫是Linux 底層的運行庫,其性能對於整個系統的運行有重要的意義。Glibc 庫包含了大量函數,其中的函數可大體分紅兩類,一類是與操做系統核心溝通的系統調用接口,它們做爲功能型函數被調用,提供對Linux 操做系統調用的包裝與預處理。另一類爲通常的函數對象,它們提供了常用的功能的實現,做爲工具型函數使用。在實踐中,有很多軟件就是依賴與Glibc版本才能安裝並運行,說白了對於Glibc版本要求是版本高了不行,低了還不成。這些編譯環境中的應用程序也和其它程序同樣必須有運行的環境,我常遇到管理員在生產中給服務器裝了最新的Linux發行版,結果應用軟件裝不上去,緣由是Glibc的版本不對,有的是寫在原發行版glibc上升級有的是降級,結果卻是整個系統的崩潰,實踐經驗告訴我,你只有選擇相應Linux發行版裏對應的glibc,例如咱們單位的一個應用軟件時在rhel3.0下開發的,那麼就得要對應的發行版,換了別的就難說了,任何本身升級或降級Glibc來適應應用軟件的作法都是不可取的,問題最後的解決方法是找到了RHEL3裝上就解決了。在表一中,我把幾個linux發行版原配的Glibc版本列出,供你們參考。
點擊圖片查看大圖
Glibc庫與核心功能組件
上圖一說明:
GCC依賴於glibc
binutils依賴於glibc (binutils提供了一系列用來建立、管理和維護二進制目標文件的工具程序,如彙編(as)、鏈接(ld)、靜態庫歸檔(ar)、反彙編)
make依賴於glibc
頭文件是在編譯時候gcc所須要的,但自己都是一些文本文件,所以沒有須要的運行環境。
經常使用工具依賴於glibc和各類須要用到的動態庫。
下表一列出了多個重要Linux發行版的Glibc的狀況
Linux發行版 Glibc版本
Redhat 9 glibc-2.3.2-5
Fedora 1 glibc-2.3.2
Redhat Enterprise Linux As 3 glibc-2.3.2-95
Redhat Enterprise Linux As 4 glibc-2.3.4
Red hat Enterprise linux 5 glibc-2.5-24
Red hat Enterprise linux 6 glibc-2.9
Centos 5.x glibc-2.5
Suse Linux Enterprise Server 9 glibc-2.3.2-92
Suse Linux enterprise Server 10 glibc-2.4.31.54
Suse Linux Enterprise Server 11 glibc-2.9
點擊圖片查看大圖
Linux發行版glibc (32)位
下面介紹幾個查詢glibc版本號的方法 :
#ls –al /lib/libc*
或者是用下面的命令也能夠實現
#rpm –qp |grep glibc
基於debian的系統經過dpkg –l | grep libc6也能夠查到,總之通常都在/usr/share/doc目錄下都能看到glibc的相關信息。
七 、小結
大部分狀況下,在遇到軟件包依賴關係問題的時候,操做系統提供的文件名字與軟件包名字都會有直接的聯繫。有可能文件的名字就是軟件包的名字。可是有些時候文件的名字與軟件包的名字會相差甚遠。此時大部分系統管理員可能光憑文件名字沒法找到對應的軟件包。此時能夠先在系統安裝光盤裏找,若是找到那時最佳選項,而後就須要藉助筆者上面談到的一些專業網站,去查詢軟件包的名字了。當系統管理員安裝了某個軟件以後,若是存在軟件包之間的依賴關係,則最好可以拿本子或者經過其餘手段記錄下來。以便下次方便實用,注意工做中的積累,相信絕大部分的軟件包依賴關係問題都會迎刃而解。
本文出自 「李晨光原創技術博客」 博客,請務必保留此出處http://chenguang.blog.51cto.com/350944/1034095python