本文大部分内容来自鸟哥的Linux私房菜,并且由作者根据自己的学习情况做了一些更改,鸟哥原文链接
1. 程序的安装方式
- 源代码安装:利用厂商释出的Tarball 来进行软件的安装,每次安装程序都需要检测系统与环境、设定编译参数、实际的编译、 最后还要依据个人喜好的方式来安装软件到指定位置。这过程很麻烦。
- 程序包安装:由软件开发者先在他们的系统上面编译好了使用者所需要的软件,然后将这个编译好的可执行的软件发给使用者来安装。而且在安装的时候还可以加上一些与这些软件相关的信息,将它建立成为数据库,之后就可以进行安装、卸载、 升级、查询与验证等等的相关功能。
2. 程序包管理器
源代码-->目标二进制格式(包括二进制程序、程序自己的库文件、配置文件、帮助文件)(C语言的话就是编译好的可直接运行的C代码)-->(把二进制程序、程序自己的库文件、配置文件、帮助文件)组织成为一个或有限几个“包”文件;
实现:安装、升级、卸载、查询、校验;
在这个软件包内还包含了预先检测系统与依赖关系的脚本,该软件会提供的所有文件信息等。最终将这个软件发布出来。用户端取得这个文件后,只要通过特定的命令来安装,那么该软件就会依照内部的脚本来检测依赖的软件是否存在,若安装的环境符合需求,就会开始安装,安装完成后还会将该软件的信息写入程序管理机制中,以达成未来可以进行升级、移除等动作。
- Debian:dpt(Debian Packet Tool),dpgk(命令行工具)以“.deg”为后缀
- Redhat:Redhat Package Manager, 简称rpm,这种方式是借鉴于debian的,以“.rpm”为后缀,最开始用prel写的,但是因为prel是脚本语言,效率太低,后改用C重新写了。最终成为了标准,被重命名为RPM is Package Manager
- S.u.S.E:使用Redhat的RPM,以“.rpm”为后缀,管理前端也叫rpm,但是研发出来一个更好的rpm库。最后Redhat在将RPM推为标准的时候,将这个库也用了。
- Gentoo:Ports,程序包管理,采用了Free BSD的方式。
- ArchLinux:新贵,研发了更好的程序包管理方式。
RPM优点
- RPM内含已经编译过的程序与配置文件等信息,可以让使用者免除重新编译的困扰;
- RPM在被安装之前,会先检查系统的硬盘容量、系统版本等,可避免文件被错误安装;
- RPM文件本身提供软件版本信息、依赖软件名称、软件用途说明、软件所含文件等信息,便于了解软件;
- RPM管理的方式使用数据库库记录RPM文件的相关参数,便于升级、移除、查询与验证。
3. 什么是RPM与SRPM
RPM:Redhat Packet Manager
RPM是以一种数据库记录的方式来将你所需要的软件安装到Linux系统的一套管理机制。
它最大的特点就是将你要安装的软件先编译过, 并且打包成为RPM机制的包,通过RPM包里头预设的数据库,记录这个软件安装的时候必须具备的依赖软件,当安装在你的Linux主机时, RPM会先依照软件里头的信息查询当前Linux主机的是否有安装依赖软件, 若满足则予以安装,若不满足则不予安装。那么安装的时候就将该软件的信息整个写入RPM的数据库中,以便未来的查询、验证与卸载等操作,这样一来的优点是:
- 由于已经编译完成并且打包完毕,所以软件传输与安装上很方便(不需要再重新编译);
- 由于软件的信息都已经记录在Linux主机的数据库上,很方便查询、升级与卸载等操作;
当这样造成了一些困扰:RPM包是应编译好的软件,所以只能在同样的编译环境中运行。也就是说,安装这个软件的系统必须要与当初编译这个软件的主机环境相同。举例来说,rp-pppoe这个软件必须要在ppp软件存在的环境中安装,如果系统尚不存在,就无法安装(可以强制安装,但是通常会出现问题)
软件管理机制的问题是:
- 软件安装的环境必须与打包时的环境需求一致或相当;
- 需要满足软件的依赖性需求;
- 卸载时需要特别小心,最底层的软件不可先移除,否则可能造成整个系统的问题;
SRPM:Source Redhat Packet Manager
这个SRPM所提供的软件内容并没有经过编译,它提供的是原始码!
通常SRPM的副档名是以***.src.rpm这种格式来命名的。不过,既然SRPM提供的是原始码,那么为什么我们不使用Tarball直接来安装就好了?这是因为SRPM虽然内容是原始码,但是他仍然含有该软件所依赖的软件说明、以及所有RPM文件所提供的信息。同时,他与RPM不同的是,他也提供了参数配置文件(就是configure与makefile)。所以,如果我们下载的是SRPM ,那么要安装该软件时,就必须要:
- 先将该软件以RPM 管理的方式编译,此时SRPM会被编译成为RPM文件;
- 然后将编译完成的RPM文件安装到Linux 系统当中
这样虽然很麻烦,但好处是:可以通过修改SRPM内的参数配置文件,然后重新编译产生能适合我们Linux环境的RPM包。
Tips:为何说CentOS是社群维护的企业版呢?Red Hat 公司的RHEL发布后,连带会将SRPM发布。社群的朋友就将这些SRPM收集起来并重新编译成为所需要的软件,而CentOS就是这么来的,所以才能号称与 Red Hat 的RHEL企业版同步!
4. rpm包命名格式
name-version-release.平台架构.rpm
-
name:软件名称
-
version:major.mirror
- 版本分为主版本号与次版本号,在主版本的架构下改动部分原始码内容,而释出一个新的版本,就是次版本。
-
release:通常就是编译的次数
- 由于同一版的软件中,可能由于有某些bug或者是安全上的顾虑,所以必须要进行小幅度的打补丁或者重设一些编译参数。配置完成之后重新编译并打包成RPM文件。因此就有了不同的打包次数。
-
平台架构:由于RPM可以适用在不同的操作平台上,但是不同的平台配置的参数还是有所差异性的。并且,我们可以针对性能比较高的CPU来进行最佳化参数的配置,这样才能使用高性能CPU所带来的硬件加速功能。所以就有所谓的i386,、i586、i686、x86_64、noarch等文件名称出现了。
-
例如:redis-3.0.2-1.centos7.x64.rpm
有的时候也会是这种格式:name-VERSION-release.os.平台架构.rpm--------##这其中os代表是系统;
拆包
把一个包当中的多种功能拆分,实现按需安装(完整的包,功能太多了,有的用不上,如果全部安装的话,一是占用空间,二是消耗资源)
- 主包:name-version-release.平台架构.rpm
- 支包(分包):name-function-version-release.硬件平台.rpm
例如
- dhcp-4.2.5-58.el7.centos.x86_64.rpm
- dhcp-common-4.2.5-58.el7.centos.x86_64.rpm-----------##命令
- dhcp-libs-4.2.5-58.el7.centos.x86_64.rpm------------------##库
5. 获取rpm程序包的途径
1. 系统发行版的光盘或官方的文件服务器(或镜像站点)
2. 项目的官方站点
3. 第三方组织
epel
搜索引擎
4. 自己编译并封装成RPM包
6. rpm命令
6.1 查询
SYNOPSIS
rpm {-q|--query} [select-options] [query-options]
OPTIONS
select-options
[PACKAGE_NAME] [-a,--all] [-f,--file FILE]
[-g,--group GROUP] {-p,--package PACKAGE_FILE]
[--hdrid SHA1] [--pkgid MD5] [--tid TID]
[--querybynumber HDRNUM] [--triggeredby PACKAGE_NAME]
[--whatprovides CAPABILITY] [--whatrequires CAPABILITY]
query-options
[--changelog] [-c,--configfiles] [--conflicts]
[-d,--docfiles] [--dump] [--filesbypkg] [-i,--info]
[--last] [-l,--list] [--obsoletes] [--provides]
[--qf,--queryformat QUERYFMT] [-R,--requires]
[--scripts] [-s,--state] [--triggers,--triggerscripts]
-q:查询
[select-options]:
-a:查询所有安装过的包;(可以对结果做grep,匹配想要的内容)
-f:查询指定文件由哪个rpm包安装生成的;
-g:查询指定包组中包含的程序包;
-p:对未安装的程序包查询,这个rpm包可能在FTP或者HTTP上的URL上,通过指定[query-options],和rpm包,查询未安装程序的信息;
--whatprovides CAPABILITY:查询指定的capability由哪个程序包提供(结合query-options选项);
--whatrequires CAPABILITY:查询指定的capability被哪个程序包依赖(结合query-options选项);
[query-options]:
-l:查看程序安装之后会产生的所有文件列表;
-i:查看程序包相关的信息,版本号,大小,所属的包组,等;
-c:查询指定程序包的安装之后会产生的配置文件;
-d:查询指定程序包的安装之后提供的文档;
-R:查询指定程序包的依赖关系;
--provides:查看指定程序包提供的所有capability;
--scripts:查看程序包自带的脚本片段(运行前、运行后、卸载前、卸载后);
--changelog:查看rpm包的更改日志(是如何演进的);
用法
rpm -qi PACKAGE 查询指定rpm包的信息
rpm -qf FILE 查询指定文件是哪个rpm包生成的
rpm -qc PACKAGE 查询指定rpm包产生了哪些/etc下的配置文件
rpm -ql PACKAGE 查询指定rpm包生成的文件列表
rpm -qd PACKAGE 查询指定rpm包提供的文档
rpm -qpl PACKAGE_FILE 查询未安装的rpm包,在安装之后会生成哪些文件
rpm -qpi PACKAGE_FILE 查询未安装的rpm包的信息
rpm -qpc PACKAGE_FILE 查询未安装的rpm包会提供哪些/etc下的配置文件
rpm -qp --scripts PACKAGE_FILE 查询未安装的rpm包,自带的脚本片段
rpm -qf --changelog FILE 查看指定文件是哪个rpm包产生的,并显示该rpm的演进信息
rpm -q --whatrequires bash 指定的capability被哪个程序包依赖;
rpm -q --whatprovides 'config(bash)' 指定的capability是那个程序包提供的;
rpm -q -R zsh 查询指定rpm包的依赖关系;
rpm -q --scripts zsh 查询指定rpm包自带的四类脚本程序代码;
Note:
要特别说明的是,在查询本机上面的RPM软件相关信息时, 不需要加上版本的名称,只要加上软件名称即可!因为它会到/var/lib/rpm这个数据库里面去查询, 所以我们可以不需要加上版本名称。但是查询某个RPM文件就不同了,我们必须要列出整个文件的完整档名才行
FILE:表示文本文件的名称; ##rpm -qf /bin/zsh
PACKAGE:表示rpm包名称; ##rpm -qi zsh
PACKAGE_FILE:表示rpm包的完整名; ##rpm -qpi zsh-5.0.2-28.el7.x86_64.rpm
6.2 安装
SYNOPSIS
rpm {-i|--install} [install-options] PACKAGE_FILE ...
INSTALL-OPTIONS
install-options
[--allfiles] [--badreloc] [--excludepath OLDPATH]
[--excludedocs] [--force] [-h,--hash]
[--ignoresize] [--ignorearch] [--ignoreos]
[--includedocs] [--justdb] [--nocollections]
[--nodeps] [--nodigest] [--nosignature] [--noplugins]
[--noorder] [--noscripts] [--notriggers]
[--oldpackage] [--percent] [--prefix NEWPATH]
[--relocate OLDPATH=NEWPATH]
[--replacefiles] [--replacepkgs]
[--test]
-i:install的意思
[install-options]
-h, --hash:输出进度条,一共50个#,每个#进度表示2%;
--test:测试安装,检查并报告依赖关系及冲突消息等,dry run模式;
--nodeps:忽略依赖关系(安装后使用可能有问题),不建议;
--replacepkgs:覆盖安装,即使已经安装在这个系统上了(可以用来覆盖配置文件);
--replacefiles:重新安装某个已经安装过的软件;
--oldpackage:允许降级,旧包替换新包;
--force:具有--replacepkgs、--replacefiles、--oldpackage的功能;
--justdb:仅更新数据库(由于RPM数据库破损或者是某些缘故产生错误时,可使用这个选项来更新软件在数据库内的相关信息);
--nosignature::在读取数据包时,不检查签名信息(不做源认证);
--nodigest:在读取数据包的时候,不检查摘要信息(不检查完整性);
--prefix:对于可重新定位的二进制包,指定新的程序安装位置。
--noscripts:不执行rpm包自带的四类脚本;
--nopre:不执行rpm包自带的preinstall脚本; ##安装过程开始之前运行脚本,%pre, --pre
--nopost:不执行rpm包自带的postinstall脚本; ##安装过程完成之后运行的脚本,$post, --nopost
--nopreun:不执行rpm包自带的preuninstall脚本; ##卸载过程开始之前运行的脚本, $preun, --nopreun
--nopostun:不执行rpm包自带的postuninstall脚本; ##卸载过程完成之后运行的脚本,$postun , $--postun
常用格式
rpm -ivh PACKAGE_FILE ... ##PACKAGE_FILE表示指定rpm包路径;
EXAMPLES
[root@Centos7 ~]# rpm -ivh zsh-5.0.2-14.el7_2.2.x86_64.rpm
Preparing... ################################# [100%]
Updating / installing...
1:zsh-5.0.2-14.el7_2.2 ################################# [100%]
[root@Centos7 ~]# rpm -qa | grep zsh
zsh-5.0.2-14.el7_2.2.x86_64
6.3 升级
SYNOPSIS
rpm {-U|--upgrade} [install-options] PACKAGE_FILE ...
rpm {-F|--freshen} [install-options] PACKAGE_FILE ...
OPTIONS
install-options
[--allfiles] [--badreloc] [--excludepath OLDPATH]
[--excludedocs] [--force] [-h,--hash]
[--ignoresize] [--ignorearch] [--ignoreos]
[--includedocs] [--justdb] [--nocollections]
[--nodeps] [--nodigest] [--nosignature] [--noplugins]
[--noorder] [--noscripts] [--notriggers]
[--oldpackage] [--percent] [--prefix NEWPATH]
[--relocate OLDPATH=NEWPATH]
[--replacefiles] [--replacepkgs]
[--test]
-U:升级或安装比较新的软件包(发现旧版本则升级,没发现则直接安装),安装之后软件包的所有其他版本将被移除;
-F:升级软件包(只完成升级旧版本),如果之前没有安装则软件也不会被安装;
[install-options]
--oldpackage:升级以替代旧的包;
--force:强制升级;具有--replacepkgs、--replacefiles、--oldpackage的功能;
Note:
- 不要对内核做升级操作;内核4.0之前的版本,要想使用新内核需要重启才可以。但是重启之后内核与系统可能发生不兼容等问题。而且Linux支持多内核版本并存,因此,直接安装新版本内核即可;
- 如果某原程序包的配置文件安装后曾被修改过,升级时,新版本的程序提供的同一个配置文件不会覆盖原有版本的配置文件,而是把新版本的配置文件重命名(FILENAME.rpmnew)后保存;
EXAMPLES
[root@Centos7 ~]# rpm -Fvh zsh-5.0.2-28.el7.x86_64.rpm
Preparing... ################################# [100%]
Updating / installing...
1:zsh-5.0.2-28.el7 ################################# [ 50%]
Cleaning up / removing...
2:zsh-5.0.2-14.el7_2.2 ################################# [100%]
[root@Centos7 ~]# rpm -qa | grep zsh
zsh-5.0.2-28.el7.x86_64
6.4 卸载
SYNOPSIS
rpm {-e|--erase} [--allmatches] [--nodeps] [--noscripts] [--test] PACKAGE_NAME ...
OPTIONS
--allmatches:卸载所有匹配指定名称的程序包的各版本;
--nodeps:忽略依赖关系;
--test:测试卸载,dry run模式;
注意:卸载和查询时都无需程序文件路径,只需给出rpm程序包名即可;安装和升级rpm程序包名需要rpm程序包文件完整路径;
:如果程序包安装后产生的配置文件如果曾被修改,卸载时,此文件通常不会被删除,而是被重命名为 .rpmsave 后缀后留存。
EXAMPLES
[root@Centos7 ~]# rpm -evh zsh
Preparing... ################################# [100%]
Cleaning up / removing...
1:zsh-5.0.2-28.el7 ################################# [100%]
[root@Centos7 ~]# rpm -qa | grep zsh
6.5 校验
验证(Verify)的功能主要在于提供系统管理员一个有用的管理机制!作用的方式是:使用/var/lib/rpm底下的数据库内容来比对目前Linux系统的环境下的所有软件文件。也就是说,当你有文件不小心遗失,或者是因为你误删了某个软件的文件,或者是不小心不知道修改到某一个软件的文件内容,就用这个简单的方法来验证一下原本的文件系统!
SYNOPSYS
rpm {-V|--verify} [select-options] [verify-options]
OPTIONS
verify-options
[--nodeps] [--nofiles] [--noscripts]
[--nodigest] [--nosignature]
[--nolinkto] [--nofiledigest] [--nosize] [--nouser]
[--nogroup] [--nomtime] [--nomode] [--nordev]
[--nocaps]
-V :后面加的是软件名称,若该软件所含的文件被更动过,才会列出来;
-Va :列出目前系统上面所有可能被更动过的文件;
-Vp :后面加的是文件名称,列出该软件内可能被更动过的文件;
-Vf :列出某个文件是否被更动过;
[verify-options]
--nodeps 不验证数据包的依赖关系;
--nodigest 在读取时,不验证数据包的完整性;
--nofiles 不验证数据包文件的任何属性是否发生改变;
--noscripts 不执行校验脚本;
--nosignature 在读取时,不验证数据包的签名;
EXAMPLES
S:文件大小发生改变
M:文件ugo访问权限发生改变
5:文件的摘要发生变化
D:设备的主/次设备号发生改变
L:路径的发生改变
U:属主发生改变
G:属组发生改变
T:mtime发生改变
P:功能的发生改变
c :配置文件
d :帮助文件
g :ghost文件,通常是该文件不被某个软件所包含,较少发生!(ghost file)
l :授权文件
r :read me文件
logrotate这个软件生成了12个文件
[root@Centos7 ~]# rpm -ql logrotate
/etc/cron.daily/logrotate
/etc/logrotate.conf
/etc/logrotate.d
/etc/rwtab.d/logrotate
/usr/sbin/logrotate
/usr/share/doc/logrotate-3.8.6
/usr/share/doc/logrotate-3.8.6/CHANGES
/usr/share/doc/logrotate-3.8.6/COPYING
/usr/share/man/man5/logrotate.conf.5.gz
/usr/share/man/man8/logrotate.8.gz
/var/lib/logrotate
/var/lib/logrotate/logrotate.status
对这些文件进行校验
[root@Centos7 ~]# rpm -V logrotate
S.5....T. c /etc/logrotate.conf ##文件大小发生变化、文件的摘要发生变化、文件的mtime发生变化、这个c表示这个文件是一个配置文件
6.6 来源合法性验证和完整性校验
谈完了软件的校验后,不知道你有没有发现一个问题,那就是,验证只能验证软件内的资讯与/var/lib/rpm/ 里面的数据库信息而已,如果该软件文件所提供的信息本身就有问题,那使用验证的手段也无法确定该软件的正确性。
来源合法性验证:
数字签名:通过md5/sha等单向加密技术,计算出一个数据的特征码(定长的),然后使用私钥加密这个特征码,并将加密后的值附加到放到RPM包里,最后发布。最后拿到这个RPM包的人,只要有对应的公钥就能解密这段特征码。因为能解密,从而验证了来源合法性,但是因为数据包有没有加密,如何确定数据包没有被更改呢?
确保数据的完整性:
拿到RPM包的人使用和发布者同样的加密算法对数据进行单向加密从而生成定长特征码,如果解密得来的特征码和自己计算数据包得来的特征码一致,就代码数据没有被篡改过。但是前面所说的方法,都是建立在公钥没有被篡改过的前提下,那但是如何确保公钥没有被篡改过呢?
确保公钥的完整性:
待续
导入密钥信息
SYNOPSIS
rpmkeys --import PUBKEY ...
rpmkeys {-K|--checksig} PACKAGE_FILE ...
OPTIONS
The --checksig option checks all the digests and signatures contained in PACKAGE_FILE to ensure the integrity and origin of the package.
--checksing
EXAMPLES
安装此组织签名的程序时,会自动执行验证;
手动验证:rpm -K PACKAGE_FILE
特定的公钥信息,可以通过以下方式显示:
rpm -qi gpg-pubkey-db42a60e
擦除都被导入的公钥,可以通过以下方式:
rpm -e gpg-pubkey-db42a60e
[root@Centos7 ~]# rpm -K zsh-5.0.2-28.el7.x86_64.rpm
zsh-5.0.2-28.el7.x86_64.rpm: rsa sha1 (md5) pgp md5 OK
[root@Centos7 ~]# rpm --checksig zsh-5.0.2-28.el7.x86_64.rpm
zsh-5.0.2-28.el7.x86_64.rpm: rsa sha1 (md5) pgp md5 OK
导入信任的包制作者的密钥:
iso文件的根目录就有例如:RPM-GPG-KEY-CentOS-7
对于CentOS发行版来说:rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
6.7 数据库重建
rpm包数据库位置:/var/lib/rpm
查询操作(包括安装、升级、卸载、查询、检验):都是通过此处的数据库进行的;
获取重建帮助
CentOS6:man rpm
CentOS7:man rpmdb
SYNOPSIS
rpm {--initdb|--rebuilddb} [--dbpath DIRECTORY] [--root DIRECTORY]
OPTIONS
--dbpath:指定数据库的路径(默认为:/var/lib/rpm)
--initdb:初始化数据库,当前无任何数据库则创建一个,当前有数据库则不执行任何操作;
--rebuilddb:重新构建,通过读取当前系统上所有已经安装过的程序包进行重新创建;无论当前是否存在数据库,都直接重新创建数据库;
EXAMPLES
rpm --rebuilddb --dbpath=/var/lib/rpm/