簡介 在Linux的早期時代(也許吧?我猜的。也可能是Unix。),想要在系統上安裝一款應用程式,是比較複雜的。需要專業的人員自行獲取程式的源代碼,並且編譯安裝,這是非常的複雜且需要一定的專業功底的,這種方式叫做源碼編譯安裝(後面會描述)。 再後來就有人/組織將這個過程簡化了,他們將事先已經編譯好的 ...
簡介
在Linux的早期時代(也許吧?我猜的。也可能是Unix。),想要在系統上安裝一款應用程式,是比較複雜的。需要專業的人員自行獲取程式的源代碼,並且編譯安裝,這是非常的複雜且需要一定的專業功底的,這種方式叫做源碼編譯安裝(後面會描述)。
再後來就有人/組織將這個過程簡化了,他們將事先已經編譯好的軟體打包後,放到互聯網上供用戶下載。用戶下載適用於自己的操作系統和硬體平臺的軟體包之後,只需要將其“解壓”,那麼該軟體包所包含的各種文件(二進位程式文件、文檔文件、庫文件和配置文件等)就會基於包作者事先定義好的位置進入各自對應的目錄下了。在CentOS上,這種打包工具就叫做rpm,即rpm安裝。
但是這種工具又存在一個缺陷,那就是它無法自動解決RPM包之間的依賴性。
假設安裝A包需要依賴於B包,安裝B包又要依賴於C包。
A --> B --> C
當你安裝A包的時候提示你要安裝B包,你安裝B包的時候又提示你要安裝C包,它無法自動去解決這個依賴關係。並且你還要自己去下載被依賴的B包和C包。
因此誕生了一種更高級的包管理器,用於解決上述的RPM的問題,在CentOS上,這種包管理器就叫做yum,即yum安裝。不過,在未來,可能是CentOS 8的時候,yum會被dnf工具所取代,在Fedora系統上,已經有dnf工具了。
在不同的Linux發行版中,這種軟體包的組織形式有點不同,見下表:
發行版 | 初級包管理器 | 高級包管理器 | 包名稱 |
RHEL系列:Red Hat、CentOS、Fedora | rpm | yum、dnf | *.rpm |
Debian、Ubuntu | dpkg | apt-get | *.deb |
S.u.S.E | rpm | zypper | *.rpm |
本文的講解順序是先講rpm安裝,再講yum安裝,最後說最複雜的源碼編譯安裝。
RPM
在當前的運維環境下,一般我們安裝某款軟體,會直接使用yum命令,而不會單獨去下載rpm包通過rpm命令來完成。
更多的是使用rpm命令去執行一下對程式包的查詢操作。
程式包的獲取
推薦從軟體的官方站點獲取,或者可以在一些比較大型的受信任的鏡像站點獲取。
- 系統發行版的光碟。
- 項目的官方站點。
- www.zabbix.com
- www.mysq.com
- 等等。
- 開源鏡像站點及一些rpm包提供站點。
- 自己動手製作rpm包。
程式包的名稱
程式包(rpm包)名稱的大概格式如下。
NAME-VERSION-RELEASE.OS.ARCH.rpm
示例
perl-5.16.3-293.el7.x86_64.rpm
NAME:軟體的名稱,例如“perl”。
VERSION:軟體的版本,一般格式為“major.minor.release”,即主版本.次版本.發行版本,例如“5.16.3”。
RELEASE:程式包的發行版,發行版可以理解為發行的次數,依次往上疊加,區別於VERSION中的release,這裡的RELEASE指的是程式包的發行版本,而不是軟體的。可能軟體的版本沒改變但是程式包再次製作發行了。例如“293”。
OS:Linux系統的大版本,CentOS 6為el6,CentOS 7為el7,el表示Enterprise Linux。
ARCH:硬體平臺。例如i386,x86_64,amd64,ppc,noarch。noarch表示該程式包不受硬體平臺的限制,可能該包均通過庫調用之類來實現自身功能。
主包與支包
程式除了以自身名稱命名的包以外,可能還存在一些其他的包用於提供與該程式相關的功能或者用於擴展該程式。
以PHP來舉例。
PHP的主包
php-5.4.16-46.el7.x86_64.rpm
PHP的支包
php-bcmath-5.4.16-46.el7.x86_64.rpm # 提供了數學計算相關的PHP擴展庫。 php-cli-5.4.16-46.el7.x86_64.rpm # 提供了PHP命令行程式/usr/bin/php。
安裝
基本語法如下。
rpm {-i|--install} [install-options] PACKAGE_FILE ...
-v:輸出詳細信息。
-vv:輸出更詳細的信息。
-h,--hash:hash marks輸出進度條,每個#表示2%的進度。
--test:測試安裝,檢查並報告依賴關係及衝突消息等,類似於乾跑(--dry-run)。
--nodeps:忽略依賴關係,忽略依賴關係之後安裝的程式包,可能可以正常運行(比如依賴的只是一個文檔類的程式包),不建議這麼做。
--replacepkgs:重新安裝,一般用於修改了程式包的某個文件無法複原的時候選擇的選項,如果重新安裝依然無法恢復修改的文件,可以事先刪除該文件再重新安裝。
--noscripts:禁用rpm包的相關腳本(scriptlet)。該選項等同於“--nopre --nopost --nopreun --nopostun”。
rpm包可以包含四種腳本:
- preinstall:安裝過程開始之前運行的腳本,%pre,--nopre
- postinstall:安裝過程完成之後運行的腳本,%post,--nopost
- preuninstall:卸載過程開始之前運行的腳本,%preun,--nopreun
- postuninstall:卸載過程完成之後運行的腳本,%postun,--nopostun
可以思考一下,比如我們安裝nginx或者php-fpm或者MySQL的時候,在系統中會產生與之對應的用於運行服務的用戶,那麼這個創建用戶的操作,應該就是rpm包的腳本所實現的了。
--nosignature:不檢查包簽名信息,即不檢查包來源的合法性。
--nodigest:不檢查包摘要信息,即不檢查包完整性信息。
包來源合法性和包完整性是什麼,在後面會描述,先知道該選項即可。
最常用的選項如下。
rpm -ivh PACKAGE_FILE ...
[root@C7 ~]# rpm -ivh zsh-5.0.2-31.el7.x86_64.rpm Preparing... ################################# [100%] Updating / installing... 1:zsh-5.0.2-31.el7 ################################# [100%]
--test選項,也可能會用到。其他選項基本不會使用到。
[root@C7 ~]# rpm -ivh --test zsh-5.0.2-31.el7.x86_64.rpm Preparing... ################################# [100%] package zsh-5.0.2-31.el7.x86_64 is already installed
因為此前已經安裝過,所以我們通過測試運行,就可以看到會有已安裝的提示。
升級
rpm {-U|--upgrade} [install-options] PACKAGE_FILE ... rpm {-F|--freshen} [install-options] PACKAGE_FILE ...
-U:表示升級或者安裝,即如果軟體此前未安裝,則可以直接安裝。
-F:明確表示只能升級,即如果軟體此前未安裝,則不會直接安裝。
一般也會結合-vh選項來使用。
rpm -Uvh PACKAGE_FILE ...
rpm -Fvh PACKAGE_FILE ...
--oldpackage:預設情況下,升級操作只可以升級到新版本,使用該選項的話,可執行降級操作。
--replacefiles:即便安裝操作會覆蓋其他程式包所安裝的文件,仍然安裝程式包。
--replacepkgs:即便程式包的某些文件已經安裝在系統上,仍然安裝程式包。
--force:等同於--replacepkgs、--replacefiles和--oldpackage。
從網上下載了zsh 5.1.1版本的,進行升級實驗。
[root@C7 ~]# rpm -Uvh --test zsh-5.1-1.gf.el7.x86_64.rpm warning: zsh-5.1-1.gf.el7.x86_64.rpm: Header V4 RSA/SHA1 Signature, key ID da8b7718: NOKEY Preparing... ################################# [100%] [root@C7 ~]# rpm -Uvh zsh-5.1-1.gf.el7.x86_64.rpm warning: zsh-5.1-1.gf.el7.x86_64.rpm: Header V4 RSA/SHA1 Signature, key ID da8b7718: NOKEY Preparing... ################################# [100%] Updating / installing... 1:zsh-5.1-1.gf.el7 ################################# [ 50%] Cleaning up / removing... 2:zsh-5.0.2-31.el7 ################################# [100%] [root@C7 ~]# rpm -qa | grep -i "zsh" zsh-5.1-1.gf.el7.x86_64
升級新的包之後,會卸載舊的包。rpm -qa命令用於查看當前系統上安裝的程式包,下文會描述。
仔細看的話,可以發現有一行警告。
warning: zsh-5.1-1.gf.el7.x86_64.rpm: Header V4 RSA/SHA1 Signature, key ID da8b7718: NOKEY
這是因為rpm包的來源合法性和包完整性無法得到驗證,我們沒有提供包提供方的key導致的,後面會描述。
降級操作。
[root@C7 ~]# rpm -q zsh zsh-5.1-1.gf.el7.x86_64 [root@C7 ~]# rpm -Uvh --oldpackage zsh-5.0.2-31.el7.x86_64.rpm Preparing... ################################# [100%] Updating / installing... 1:zsh-5.0.2-31.el7 ################################# [ 50%] Cleaning up / removing... 2:zsh-5.1-1.gf.el7 ################################# [100%] [root@C7 ~]# rpm -q zsh zsh-5.0.2-31.el7.x86_64
註意事項:
- 不要對內核做升級操作;若想要使用新版本的內核,Linux支持多內核版本並存,因此直接安裝新版本內核即可。
- 如果某原程式包的配置文件在安裝後曾被修改過,升級時,新版程式包提供的同一個配置文件不會覆蓋老版本已修改過的配置文件,而是把新版本的配置文件重命名(FILENAME.rpmnew)後提供。
卸載
rpm {-e|--erase} [--allmatches] [--nodeps] [--noscripts] [--test] PACKAGE_NAME ...
註意,在安裝和升級的過程中,rpm命令的操作對象都是rpm包文件的名稱(PACKAGE_FILE),例如“zsh-5.0.2-31.el7.x86_64.rpm”。
而卸載的時候,只需要rpm包名(PACKAGE_NAME)即可,例如“zsh”。
--allmatches:卸載所有匹配PACKAGE_NAME的所有版本的程式包。
我這裡無法測試該選項,例如zsh,無論我升級還是降級,rpm都只會保留一個版本的zsh,因此我不知道如何測試該選項。
不過一般卸載所使用到的選項並不多,和安裝一樣,使用一些通用的選項即可。
[root@C7 ~]# rpm -evh zsh Preparing... ################################# [100%] Cleaning up / removing... 1:zsh-5.0.2-31.el7 ################################# [100%] [root@C7 ~]# rpm -q zsh package zsh is not installed
查詢
查詢才是rpm使用中最經常用到的操作。因為安裝、升級和卸載都可以使用yum命令來完成,而查詢我們則基本上是使用rpm命令。
rpm {-q|--query} [select-options] [query-options]
[select-options]
PACKAGE_NAME:查詢指定的程式包是否已安裝,若已安裝則會顯示其版本。
[root@C7 ~]# rpm -q bash bash-4.2.46-30.el7.x86_64
-a, --all:查詢所有已安裝的程式包,可以結合管道+grep命令過濾。
[root@C7 ~]# rpm -qa | grep -i "bash" bash-4.2.46-30.el7.x86_64 bash-completion-2.1-6.el7.noarch
-f, --file FILE:查詢出指定的FILE是哪個程式包的。
[root@C7 ~]# rpm -qf /bin/bash bash-4.2.46-30.el7.x86_64
-g, --group GROUP:查詢某個程式包組包含哪些程式包。註意,這裡的GROUP,並不是通過yum grouplist中所看到的程式包組名稱,而是通過-i選項所查詢到的包詳細信息中的GROUP!
例如我們常安裝的包組為Development Tools,就不是這裡所指的GROUP。即便已安裝了該包組。
[root@C7 ~]# rpm -qg "Development Tools" group Development Tools does not contain any packages
[root@C7 ~]# rpm -qi bash | grep -i "^group" Group : System Environment/Shells [root@C7 ~]# rpm -qg "System Environment/Shells" bash-4.2.46-30.el7.x86_64 tcsh-6.18.01-15.el7.x86_64
-p, --package PACKAGE_FILE:對未安裝的程式包執行查詢操作,查詢的內容與query-options相關。
在query-options中,許多的選項可以用於查看已安裝的程式包的信息;
但是如果我們擁有一個RPM包文件,但是不打算安裝它,想查看此RPM包所包含的文件;
就可以使用命令“rpm -qpl PACKAGE_FILE”,這就是p選項的用法;
例如,假設我們本機沒有安裝zsh,那麼我們就無法查詢其相關信息了。
[root@C7 ~]# rpm -qi zsh
package zsh is not installed
但如果我們有程式包文件的話,就可以藉助-p選項來實現查詢的功能,只不過這裡的命令參數就是PACKAGE_FILE而不是PACKAGE_NAME了。
[root@C7 ~]# rpm -qpi zsh-5.0.2-31.el7.x86_64.rpm
--whatprovides CAPABILITY:查詢所有包中具備某種能力(capability)的程式包。這裡的能力指的是什麼,就需要看底下的query-options中的--provides和-R選項了。
首先我們基於下文的選項,可以知道bash程式包提供了以下能力。
[root@C7 ~]# rpm -q --provides bash /bin/bash /bin/sh bash = 4.2.46-30.el7 bash(x86-64) = 4.2.46-30.el7 config(bash) = 4.2.46-30.el7
以“/bin/bash”這個能力來舉例,我們可以查看哪些程式包提供了該能力。
[root@C7 ~]# rpm -q --whatprovides "/bin/bash" bash-4.2.46-30.el7.x86_64
而如果能力是那種帶有等於號與版本信息的,應該忽略掉等於號和版本信息,只保留能力名稱,並且需要使用單引號或者雙引號。
[root@C7 ~]# rpm -q --whatprovides "bash(x86-64) = 4.2.46-30.el7" no package provides bash(x86-64) = 4.2.46-30.el7 [root@C7 ~]# rpm -q --whatprovides "bash(x86-64)" bash-4.2.46-30.el7.x86_64 [root@C7 ~]# rpm -q --whatprovides bash(x86-64) -bash: syntax error near unexpected token `(' [root@C7 ~]# rpm -q --whatprovides 'bash(x86-64)' bash-4.2.46-30.el7.x86_64
--whatrequires CAPABILITY:查詢所有包中需要某種能力(capability)的程式包。
[root@C7 ~]# rpm -q --whatrequires "/bin/bash" nss-softokn-freebl-3.34.0-2.el7.x86_64 copy-jdk-configs-3.3-2.el7.noarch iproute-4.11.0-14.el7.x86_64 xorg-x11-xinit-1.3.4-2.el7.x86_64 ...
我猜測,rpm包應該就是基於包的能力(capability)來決定包與包之間的依賴關係的。
能力這塊,目前知道即可,我們並不需要手工去查詢來解決依賴關係,因為我們有yum工具。
[query-options]
--changelog:顯示程式包的變更日誌(changelog),這裡的變更日誌指的是RPM程式包的,而非軟體源碼包的。程式包的changelog和軟體的changelog的區別可能在於,比如軟體源代碼可以不改變,但是程式包的打包方式改變了,例如部分文件的存放位置發生了修改。
[root@C7 ~]# rpm -q --changelog bash | head * Mon Sep 25 2017 Siteshwar Vashisht <[email protected]> - 4.2.46-30 - Check for multibyte characters in commands Resolves: #1487615 * Thu Aug 03 2017 Siteshwar Vashisht <[email protected]> - 4.2.46-29 - Fix a pipe fd leak in process substitution Resolves: #1473245 * Tue Mar 07 2017 Kamil Dudka <[email protected] - 4.2.46-28 - CVE-2016-9401 - Fix crash when '-' is passed as second sign to popd
-l, --list:查詢程式包所包含的所有文件(二進位程式文件、文檔文件、庫文件和配置文件等)。
[root@C7 ~]# rpm -ql bash /etc/skel/.bash_logout ... /usr/bin/alias /usr/bin/bash ... /usr/share/doc/bash-4.2.46 ... /usr/share/man/man1/..1.gz ...
-c, --configfiles:僅查詢程式包所包含的配置文件。
[root@C7 ~]# rpm -qc bash /etc/skel/.bash_logout /etc/skel/.bash_profile /etc/skel/.bashrc
-d, --docfiles:僅查詢程式包所包含的文檔文件。
[root@C7 ~]# rpm -qd bash /usr/share/doc/bash-4.2.46/COPYING ... /usr/share/man/man1/..1.gz ...
-i, --info:查詢程式包的詳細信息(information)。這個是比較重要的信息!
[root@C7 ~]# rpm -qi bash Name : bash # 程式包名稱。 Version : 4.2.46 # 程式包版本。 Release : 30.el7 # 程式包發行版,包含了OS。 Architecture: x86_64 # 程式包適用硬體平臺。 Install Date: Thu 27 Sep 2018 03:50:45 PM CST # 安裝日期。 Group : System Environment/Shells # 這裡的group,就是上面“rpm -qg GROUP”中的group。 Size : 3667709 License : GPLv3+ Signature : RSA/SHA256, Wed 25 Apr 2018 06:54:19 PM CST, Key ID 24c6a8a7f4a80eb5 Source RPM : bash-4.2.46-30.el7.src.rpm # RPM源碼包,和純源碼包又完全不同,後面會描述。 Build Date : Wed 11 Apr 2018 08:55:22 AM CST Build Host : x86-01.bsys.centos.org Relocations : (not relocatable) Packager : CentOS BuildSystem <http://bugs.centos.org> Vendor : CentOS # 程式包製作商。 URL : http://www.gnu.org/software/bash # 軟體相關的官方站點。 Summary : The GNU Bourne Again shell # 軟體的簡要信息。 Description : # 軟體的詳細信息。 The GNU Bourne Again shell (Bash) is a shell or command language interpreter that is compatible with the Bourne shell (sh). Bash incorporates useful features from the Korn shell (ksh) and the C shell (csh). Most sh scripts can be run by bash without modification.
--provides:查詢程式包所提供的能力(capability)。
[root@C7 ~]# rpm -q --provides bash /bin/bash /bin/sh bash = 4.2.46-30.el7 bash(x86-64) = 4.2.46-30.el7 config(bash) = 4.2.46-30.el7
-R, --requires:查詢程式包所依賴的能力(capability)。
[root@C7 ~]# rpm -qR bash /bin/sh config(bash) = 4.2.46-30.el7 libc.so.6()(64bit) libc.so.6(GLIBC_2.11)(64bit) libc.so.6(GLIBC_2.14)(64bit) libc.so.6(GLIBC_2.15)(64bit) libc.so.6(GLIBC_2.2.5)(64bit) libc.so.6(GLIBC_2.3)(64bit) libc.so.6(GLIBC_2.3.4)(64bit) libc.so.6(GLIBC_2.4)(64bit) libc.so.6(GLIBC_2.8)(64bit) libdl.so.2()(64bit) libdl.so.2(GLIBC_2.2.5)(64bit) libtinfo.so.5()(64bit) rpmlib(BuiltinLuaScripts) <= 4.2.2-1 rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(FileDigests) <= 4.6.0-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1 rtld(GNU_HASH) rpmlib(PayloadIsXz) <= 5.2-1
--scripts:查詢程式包在安裝和卸載過程中使用的特殊腳本程式。我自己查了bash和postfix程式包,發現可使用shell script和lua語言編寫。
[root@C7 ~]# rpm -q --scripts bash postinstall scriptlet (using <lua>): ... postuninstall scriptlet (using <lua>): -- Run it only if we are uninstalling ...
包來源合法性與包完整性
當我們從網上下載了一個rpm包之後,如何確保這個rpm包就是該站點所提供的?如何確保rpm包沒有被第三方所篡改呢?
這就需要依賴於rpm包的來源合法性和包完整性驗證了。
來源合法性驗證依賴於數字簽名,包完整性驗證依賴於消息摘要演算法。
rpm包實現包來源合法性和包完整性檢測的原理如下:
- 包製作者使用單向加密演算法(比如md5)對包進行加密得到校驗碼(或者說是消息摘要);
- 包製作者使用自己的私鑰去加密校驗碼,並將加密後的校驗碼附加在包的尾部;
- 包使用者使用包製作者提供的公鑰對包尾部的加密後的校驗碼進行解密,如果解密成功,則證明包的來源是合法的(確實是包製作者本人發出的,這裡涉及到非對稱加密的概念);
- 包使用者使用和包製作者相同的單向加密演算法(比如md5)對包進行加密得到校驗碼,如果此校驗碼和剛纔包使用者使用公鑰解密後得到的校驗碼一致,那麼就證明瞭包的完整性(包在傳輸的過程中未被篡改)。
這裡涉及到加密與解密的這些理論知識,將來應該會寫一篇文章來詳細闡述。
如果我們想檢測一個rpm,那麼我們就需要一個公鑰文件,這個文件,一般是包製作方會提供,在系統鏡像文件中也會有。
系統安裝好之後,在“/etc/pki/rpm-gpg/”目錄下會有公鑰(密鑰有公鑰和私鑰兩種)文件。
[root@C7 ~]# ls -l /etc/pki/rpm-gpg/ total 16 -rw-r--r--. 1 root root 1690 Apr 29 2018 RPM-GPG-KEY-CentOS-7 -rw-r--r--. 1 root root 1004 Apr 29 2018 RPM-GPG-KEY-CentOS-Debug-7 -rw-r--r--. 1 root root 1690 Apr 29 2018 RPM-GPG-KEY-CentOS-Testing-7 -rw-r--r-- 1 root root 1662 Oct 3 2017 RPM-GPG-KEY-EPEL-7
當我們有了密鑰後,就可以將其導入rpm,用作後續的校驗操作。
CentOS 6和CentOS 7操作有些許不同,因為6和7預設的rpm版本不一樣。6的寫法,在7上也可以使用。
[root@C6 ~]# rpm -q rpm rpm-4.8.0-55.el6.x86_64 [root@C7 ~]# rpm -q rpm rpm-4.11.3-35.el7.x86_64
CentOS 6:rpm --import PUBKEY ... CentOS 7:rpmkeys --import PUBKEY ...
有了key之後,就可以對程式包進行檢測了。
CentOS 6:rpm {-K|--checksig} [--nosignature] [--nodigest] PACKAGE_FILE ... CentOS 7:rpmkeys {-K|--checksig} PACKAGE_FILE ...
zsh-5.0.2版本的,此前從阿裡雲的CentOS 7鏡像下載,因為系統自帶了key,因此可以檢測通過。而zsh-5.1.1則沒有key,因此無法檢測。
[root@C7 ~]# rpmkeys -K zsh-5.0.2-31.el7.x86_64.rpm zsh-5.0.2-31.el7.x86_64.rpm: rsa sha1 (md5) pgp md5 OK [root@C7 ~]# rpmkeys -K zsh-5.1-1.gf.el7.x86_64.rpm zsh-5.1-1.gf.el7.x86_64.rpm: RSA sha1 ((MD5) PGP) md5 NOT OK (MISSING KEYS: (MD5) PGP#da8b7718)
除了主動檢查包以外,每次在安裝/升級等操作的時候,rpm也會自動去檢查的,例如上文我們看到的那個警告信息。
warning: zsh-5.1-1.gf.el7.x86_64.rpm: Header V4 RSA/SHA1 Signature, key ID da8b7718: NOKEY
相關的幫助。
CentOS 6:man rpm CentOS 7:man rpmkeys
校驗
rpm {-V|--verify} [select-options] [verify-options]
校驗操作會將已安裝的文件的信息和rpm資料庫的元數據中記錄的信息做比較,這些信息包括了文件大小、摘要(digest)、許可權、類型、屬主和屬組等。如果這些信息有改變,那麼就會將其顯示出來。
如果在安裝的時候沒有安裝該文件的話,則會忽略未安裝的文件。例如,在安裝的時候使用了--excludedocs選項,那麼在校驗的時候就會忽略文檔類型的文件。
[root@C7 ~]# rpm -V bash
[root@C7 ~]#
如果程式包中的文件均為改動過,那麼就不會有任何的輸出。
接下來我們修改某個配置文件,加一行註釋;修改了版權文件的時間;修改cd程式文件的屬主和屬組。
[root@C7 ~]# vim /etc/skel/.bash_logout [root@C7 ~]# touch /usr/share/doc/bash-4.2.46/COPYING
[root@C7 ~]# chown zwl:zwl /usr/bin/cd
再次校驗。
[root@C7 ~]# rpm -V bash S.5....T. c /etc/skel/.bash_logout .....UG.. /usr/bin/cd .......T. d /usr/share/doc/bash-4.2.46/COPYING
在輸出的內容中,由三個部分構成。
第一個部分由9個欄位構成。小數點“.”表示檢查沒問題。如果出現問號“?”的話,表示無法檢查,比如可能因為許可權問題導致無法讀取文件信息。
- S:Size,文件大小改變。
- M:Mode,許可權或者文件類型改變。
- 5:消息摘要改變,一般是md5演算法;消息摘要不同,意味著文件內容發生了改變。
- D:Device,設備的設備號不匹配。
- L:readLink(2)路徑不匹配。
- U:User,屬主改變。
- G:Group,屬組改變。
- T:mTime,文件修改時間改變。
- P:caPabilities,包能力改變。
第二個部分是屬性標記,可有可無的。
- c:%config,配置文件。
- d:%doc,文檔文件。
- g:%ghost file (i.e. the file contents are not included in the package payload).
- l:%license,許可證文件。
- r:%readme,類似文檔文件。
RPM資料庫
rpm的資料庫位於目錄/var/lib/rpm/中,rpm基於這些資料庫的內容才可以完成它上述的功能。資料庫文件的格式是伯克利DB。
[root@C7 ~]# file /var/lib/rpm/* /var/lib/rpm/Basenames: Berkeley DB (Btree, version 9, native byte-order) /var/lib/rpm/Conflictname: Berkeley DB (Btree, version 9, native byte-order) /var/lib/rpm/Dirnames: Berkeley DB (Btree, version 9, native byte-order) /var/lib/rpm/Group: Berkeley DB (Btree, version 9, native byte-order) /var/lib/rpm/Installtid: Berkeley DB (Btree, version 9, native byte-order) /var/lib/rpm/Name: Berkeley DB (Btree, version 9, native byte-order) /var/lib/rpm/Obsoletename: Berkeley DB (Btree, version 9, native byte-order) /var/lib/rpm/Packages: Berkeley DB (Hash, version 9, native byte-order) /var/lib/rpm/Providename: Berkeley DB (Btree, version 9, native byte-order) /var/lib/rpm/Requirename: Berkeley DB (Btree, version 9, native byte-order) /var/lib/rpm/Sha1header: Berkeley DB (Btree, version 9, native byte-order) /var/lib/rpm/Sigmd5: Berkeley DB (Btree, version 9, native byte-order) /var/lib/rpm/Triggername: Berkeley DB (Btree, version 9, native byte-order)
rpm {--initdb|--rebuilddb} [-v] [--dbpath DIRECTORY] [--root DIRECTORY]
--initdb:初始化資料庫,即創建一個新的,如果原本已經有的話,就不創建。
--rebuilddb:重建資料庫,一般如果資料庫損壞了,可使用。它會基於已安裝的包頭(package header)來重建資料庫索引。
--dbpath:指定資料庫的位置,預設是/var/lib/rpm/。
--root:指定rpm資料庫所基於的根文件系統路徑。預設應該是系統根“/”。註:該選項解釋不確定。
[root@C7 ~]# rpm --initdb -v --dbpath=/tmp/rpm_test [root@C7 ~]# ls /tmp/rpm_test/ Basenames Conflictname __db.001 __db.002 __db.003 Dirnames Group Installtid Name Obsoletename Packages Providename Requirename Sha1header Sigmd5 Triggername
有嘗試指定了--root選項的值為/usr或者/usr/local,均無法初始化出資料庫文件。
YUM
正如文章開頭所描述的,yum是一款基於rpm包的包管理器。相對於rpm,它自動幫我們解決了包下載以及包依賴性的問題。
yum是一款C/S架構的工具。客戶端即為本地的Linux端,需要安裝軟體的那一端;伺服器端即為遠程倉庫(repository)端,也叫做yum源。
倉庫端除了存放眾多的RPM包以外,還存放了相關的元數據(應該是記錄包之間的依賴關係等)repodata目錄。
存放repodata目錄的地址,即為yum源地址,例如該示例中的“https://mirrors.aliyun.com/zabbix/zabbix/3.0/rhel/7/x86_64/”。
yum源的地址及倉庫的地址。地址可使用的協議如下。一般最常見的還是http協議,file協議用於指定本地yum源。
ftp:// http:// nfs:// file:///
YUM配置文件
在使用yum之前,我們必須正確配置好yum的配置文件,系統安裝好之後,預設就已經幫我們啟用了一些配置文件。
主配置文件:/etc/yum.conf,這裡存放的是倉庫相關的通用配置[main]。
倉庫配置文件:/etc/yum.repos.d/*.repo,這裡才是每一個倉庫所對應的配置文件,比如zabbix和MySQL可以存放在不同的配置文件中,zabbix.repo和mysql.repo。
一般來說,主配置文件,我們是不用去改動的,更多的是管理倉庫配置文件。
主配置
主配置文件中,一般只有一個[main]配置段,它管理的是全局配置。該配置段,也只能有一個。
我們來看下系統預設提供的。
[main] cachedir=/var/cache/yum/$basearch/$releasever keepcache=0 debuglevel=2 logfile=/var/log/yum.log exactarch=1 obsoletes=1 gpgcheck=1 plugins=1 installonly_limit=5 bugtracker_url=http://bugs.centos.org/set_project.php?project_id=23&ref=http://bugs.centos.org/bug_report_page.php?category=yum distroverpkg=centos-release
在一些表示“是”和“否”的配置中,會使用1(true)或者0(false)來表示。
cachedir:yum的緩存和資料庫存儲目錄。對於當前系統來說就是“/var/cache/yum/x86_64/7/”。
keepcache:在安裝成功後,是否保持頭和包的緩存。值為1或者0,預設是1(表示保持)。
debuglevel:debug消息輸出級別。範圍是0~10,預設是2。
logfile:日誌文件位置,需要寫全路徑(含目錄名和文件名)。
exactarch:
obsoletes:只在更新/升級程式包時有效,應該是允許包含廢棄/陳舊(obsolete)數據包,在發行版升級時(例如CentOS 6 --> CentOS 7),比較有用。預設是1。
gpgcheck:是否執行GPG簽名檢測,預設是0。如果在[main]配置中設置了,那麼它會應用於所有的倉庫中。目前還沒在man手冊中看到明確的說法,不過個人認為,如果[main]和倉庫的配置存在相同的配置項的話,那麼在[main]中配置的會成為倉庫的預設配置;如果兩邊均配置了,則應該是以倉庫配置為準。
plugins:是否啟用插件,預設是0。插件用於擴展yum功能,我的系統預設有2個插件。
fastestmirror:用於根據下載速度將yum源排序,然後選擇下載最快的yum源來使用。
langpacks:條件式語言支持包,應該是和語言(中英文這類)相關。
installonlypkgs:程式包名稱列表。在該列表中的程式包,只可以被安裝,不可以被更新。一般都是內核相關的程式包,具體見man手冊。
installonly_limit:在installonlypkgs列表中,一次性同時安裝的程式包數量,預設是3。這個配置項應該是和“installonlyn”插件比較有關係。
bugtracker_url:應該是bug追蹤反饋的一個地址。
distroverpkg:這裡配置的是一個rpm包的名字。一般是system-release(releasever)、redhat-release或者centos-release。對於我的系統來說,它是centos-release。這個包用來告訴yum我們所使用的Linux發行版是哪種,並且該包還提供了發行版的GPG密鑰、repo文件等。
倉庫配置
[repositoryid] name=Some name for this repository baseurl=url://path/to/repository/
repositoryid:倉庫的唯一標識符,一般是一個單詞。
name:倉庫的描述信息。
baseurl:倉庫的地址,也叫yum源地址。這個地址下必須有“repodata”目錄。URL可以有多個,但是官方不建議。URL也可以帶上HTTP的基本驗證信息。
baseurl=http://user:[email protected]/
enabled:是否啟用該倉庫。
gpgcheck:同理[main]配置段。
repo_gpgcheck:是否對倉庫的repodata執行GPG 簽名檢查。
gpgkey:指定GPG密鑰,如果此前沒有導入過的話,則yum會自動導入。
enablegroups:是否允許yum安裝程式包組,即yum groupinstall,預設為1。
failovermethod:當yum源聯繫不上時,使用的故障轉移辦法。roundrobin表示隨機,註意不是輪詢;priority表示按順序。
username和password:yum源URL的基本驗證信息,可寫在URL中,或者[main]配置段,或者倉庫配置段。
cost:倉庫的開銷,開銷越小越優先。預設是1000。
變數
配置文件中是可以包含變數的。
$releasever:如果是CentOS 6的話,則該值為6;同理,CentOS 7的值為7。
$arch:系統的硬體平臺(architecture),常見的有i386、i486、i586、x86_64等等。
$basearch:基礎硬體平臺,例如如果系統是i486、i586之類的,則會顯示為i386。
$uuid:根據當前機器生成的唯一標識符,值位於/var/lib/yum/uuid文件中。
$YUM0-$YUM9:會被系統同名環境變數所取代,一般用於用戶自定義。
baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/ 等同於 baseurl=http://mirror.centos.org/centos/7/os/x86_64/
YUM的命令
基本語法。
yum [options] [command] [package ...]
yum的具體功能,通過command來實現。
倉庫相關
repolist [all|enabled|disabled]
用於列出倉庫信息,預設只列出已啟用的。
[root@C7 ~]# yum repolist Loaded plugins: fastestmirror, langpacks # 載入yum插件 Loading mirror speeds from cached hostfile # 插件輸出信息,這部分輸出後面會忽略 * base: mirrors.aliyun.com * epel: mirrors.aliyun.com * extras: mirrors.huaweicloud.com * updates: mirrors.aliyun.com repo id repo name status # 狀態,即程式包個數 !base/7/x86_64 # repo id前的感嘆號表示該倉庫的元數據過期了。 CentOS-7 - Base 10,019 !epel/x86_64 Extra Packages for Enterprise Linux 7 - x86_64 13,139 !extras/7/x86_64 CentOS-7 - Extras 413 !updates/7/x86_64 CentOS-7 - Updates 1,840
可以跟上repo id或者repo name來顯示對應的倉庫。
# yum repolist REPO_ID # yum repolist REPO_NAME
可以通過-v選項或者repoinfo顯示倉庫詳細信息。
# yum repolist -v ... # yum repoinfo ...
程式包列表
list [...]
預設情況下,列出所有的程式包,程式包名稱支持globbing風格。
yum list [all | glob_exp1] [glob_exp2] [...]
可以列出程式包名稱、具體的版本信息以及來自哪個倉庫。@REPO_ID(中的@)表示這是一個已安裝的包。
dwz.x86_64 0.11-3.el7 @base dyninst.x86_64 9.3.1-1.el7 @anaconda # anaconda表示的應該是隨系統安裝的時候裝的。
列出未安裝但是可安裝的包。
yum list available [glob_exp1] [...]
列出所有可更新的包。
yum list updates [glob_exp1] [...]
更多的相關命令,查看“man yum”中的“LIST OPTIONS”。
程式包安裝
install package1 [package2] [...]
預設情況下,會安裝倉庫中最新版本的程式包。安裝對象,也可以直接是一個本地的rpm文件,當需要依賴其他包時,yum會自動解決。
程式包重裝
reinstall package1 [package2] [...]
程式包更新/升級
更新就是升級的意思。
update [package1] [package2] [...]
如果沒指明package的話,那麼預設情況下,yum會更新所有已安裝的程式包。
如果在更新過程中,被依賴的程式包也需要更新,那麼yum會更新;如果新增了被依賴的程式包,那麼yum也會新安裝。
upgrade [package1] [package2] [...]
upgrade等同於“update --obsoletes”或者主配置文件的[main]中啟用了“obsoletes”。英文原意是“在計算中包含廢棄的包”,我猜測可能是保留這些廢棄的包吧。
可以在更新之前,查看有哪些程式包可以更新。
# yum check-update
除了升級以外,還可以降級。
downgrade package1 [package2] [...]
一般降級的時候,在包名中會指明版本號,如果沒指明的話,則安裝最新版的上一版。
程式包卸載
remove | erase package1 [package2] [...]
在卸載的同時,會將依賴於該程式包的程式包一併卸載。yum程式包本身位於protected_packages配置中,所以不會被誤卸載。
程式包能力
provides | whatprovides feature1 [feature2] [...]
這裡的feature,應該等同於上文所說的包的能力(capability)。
根據能力,來查詢哪些包支持這些。
# yum provides "bash(x86-64)"
緩存相關
清理緩存。
clean [ packages | metadata | expire-cache | rpmdb | plugins | all ]
這裡所清理的緩存,都是那些已啟用的倉庫,如果想清理所有(含未啟用的),請使用“--enablerepo='*'”選項。
我自己都嘗試清理了一下,應該都是緩存,所以下次運行的時候,yum還會從源中去獲取這些數據的,應該問題不大。
但是不要自己通過rm去刪除yum的緩存(“/var/cache/yum/”)。
重新生成緩存。會從伺服器端下載並生成元數據。
makecache [fast]
如果傳遞了fast參數,那麼就等同於運行了“yum clean expire-cache”。
程式包搜索
search string1 [string2] [...]
當你不知道程式包名稱的時候,可以使用該選項。
預設情況下,搜索包的name和summary欄位(rpm -qi信息)。如果沒找著的話,會嘗試description和url欄位。可通過傳遞all作為第一個參數來搜索全部欄位。
# yum search all database
程式包依賴
deplist package1 [package2] [...]
會顯示程式包所依賴的能力,以及可提供該能力的對應的程式包。瞭解即可,yum可自行解決依賴關係。
程式包組相關
groupinstall group1 [group2] [...]
groupupdate group1 [group2] [...]
grouplist [hidden] [groupwildcard] [...]
groupremove group1 [group2] [...]
groupinfo group1 [...]
註意:上面的語法,是CentOS 6上的yum的,在CenTOS 7上會稍微有點不同。
瞭解即可,基本上會使用到的也就只有安裝而已。常見是安裝開發工具。
# yum group install "Development Tools"
其他的,詳見man手冊。
YUM的選項
--nogpgcheck:禁止進行gpgcheck。
-y, --assumeyes:自動回答yes安裝。
-q, --quiet:靜默模式。