1. 基础知识
1.1. 软件运行和编译
1.1.1. ABI:Application Binary Interface
Windows与Linux不兼容
ELF(Executable and Linkable Format)
PE(Portable Executable)
库级别的虚拟化:
Linux: WINE
Windows: Cygwin
1.1.2. API:Application Programming Interface
POSIX:Portable OS
- 程序源代码 –> 预处理 –> 编译 –> 汇编 –> 链接
静态编译:.a
动态编译:.so - 注意:linux(Centos)中大多用源码而不用编译好的二进制可执行文件,是因为源码编译可以定制自己想要的功能模块,同时可以在不同的操作系统上进行编译,在不同的操作系统上运行。因此大多用源码,而不用特定的编译好的二进制文件。
例如C语言编译过程: 
1.2. 静态和动态链接
链接主要作用是把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确地衔接,分为静态链接和动态链接
- 静态链接
- 把程序对应的依赖库复制一份到包
- libxxx.a
- 嵌入程序包
- 升级难,需重新编译
- 占用较多空间,迁移容易
- 动态链接
- 只把依赖加做一个动态链接
- libxxx.so
- 连接指向
- 占用较少空间,升级方便
图示: 
C语言静态链接: 
Java程序运行: 
1.3. 开发语言
- 系统级开发
C
C++ - 应用级开发
java
Python
go
php
perl
delphi
ruby
2. 包和包管理器
最初只有.tar.gz的打包的源码文件,用户必须编译每个他想在GNU/Linux上运行的软件
用户们急需系统提供一种方法来管理这些安装在机器上的软件,当Debian诞生时,这样一个管理工具也就应运而生,它被命名为dpkg。从而著名的“package”概念第一次出现在GNU/Linux系统中,稍后Red Hat才开发自己的“rpm” 包管理系统
注意:包里面是已经编译好的二进制文件以及其他相关文件,因此不同的系统不同
包的组成:
二进制文件、库文件、配置文件、帮助文件
(这也就是说一个rpm包只需把它解压到相应的默认软件位置即可,它里面的二进制文件已经是编译好的可执行文件,无需编译)程序包管理器:
debian: deb文件, dpkg包管理器
redhat: rpm文件, rpm包管理器
rpm:Redhat Package Manager
RPM Package Manager附加复习命令:统计centos自带光盘内的rpm包的个数,以及它采用的cpu架构和各架构包的数量
统计数量:(注意ls后面不能加引号,find后面必须加引号)
# ls "*.rpm" |wc -l
ls: cannot access *.rpm: No such file or directory
0
# ls *.rpm |wc -l
10019
# find -name "*.rpm" |wc -l
10019
统计CPU架构种类和采用这种CPU架构的包的数量:
# ls *.rpm |sed -r "s/^.*\.(.*)\.rpm$/\1/" |sort |uniq -c
2258 i686
3122 noarch
4639 x86_64
或者用grep:
16:15[root@centos7 /run/media/root/CentOS 7 x86_64/Packages]# find -name "*.rpm" |egrep -o "[^.]+\.rpm$"|cut -d. -f1|sort|uniq -c
2258 i686
3122 noarch
4639 x86_64
还有比较轻松的方法:(用rev两次颠倒)
16:18[root@centos7 /run/media/root/CentOS 7 x86_64/Packages]# ls *.rpm | rev |cut -d. -f2 |rev |sort|uniq -c
2258 i686
3122 noarch
4639 x86_64
- 注意,ls 查询中的通配符
*不能显示.开头的文件(隐藏文件和当前目录.),但是find -name中的通配符*, 可以查询.开头的隐藏文件,可以通过查看find的man帮助也可得知,里面有介绍。
2.1. 包命名
- 源代码: name-VERSION.tar.gz|bz2|xz VERSION: major.minor.release
- rpm包命名方式: name-VERSION-release.arch.rpm 例:bash-4.2.46-19.el7.x86_64.rpm VERSION: major.minor.release release:release.OS 常见的arch: x86: i386, i486, i586, i686 x86_64: x64, x86_64, amd64 powerpc: ppc 跟平台无关:noarch
2.2. 包命名和工具
- 包:分类和拆包
Application-VERSION-ARCH.rpm: 主包
Application-devel-VERSION-ARCH.rpm 开发相关子包
Application-utils-VERSION-ARHC.rpm 工具相关其它子包
Application-libs-VERSION-ARHC.rpm 库相关其它子包
- 包之间:可能存在依赖关系,甚至循环依赖
- 解决依赖包管理工具:
yum:rpm包管理器的前端工具
apt:deb包管理器前端工具
zypper:suse上的rpm前端管理工具
dnf:Fedora 18+ rpm包管理器前端管理工具(centos8)
2.3. 库文件—{ldd,ldconfig}
- 查看二进制程序所依赖的库文件
ldd /PATH/TO/BINARY_FILE
例如ldd /bin/cat - 管理及查看本机装载的库文件
ldconfig 加载配置文件中指定的库文件
/sbin/ldconfig –p 显示本机已经缓存的所有可用库文件名及文件路径
- 映射关系
配置文件:/etc/ld.so.conf,/etc/ld.so.conf.d/*.conf
缓存文件:/etc/ld.so.cache
2.3.1. 附加linux光盘修复初级步骤
- 如果是在虚拟机中,启动时按esc按键,进入光盘引导启动,它会加载一个光盘内的linux系统,如果是物理机,用F12等按键进入bios进行光盘引导
- 启动后选择救援模式,然后继续(按1键continue),然后它会提示系统挂载到了/mnt/sysimage ,也就是说原来的linux系统的根目录/ 现在就是/mnt/sysimage这个目录了。如果想要更改它,把当前的根目录(光盘引导启动的小linux系统的根目录)和原来损坏的linux根目录挂载在一起,可以用chroot /mnt/sysimage命令。(change root 即为修改根命令。)
- 然后进行其他救援操作即可
2.4. 包管理器
- 程序包管理器: 功能:将编译好的应用程序的各组成文件打包一个或几个程序包文件,从而方便快捷地实现程序包的安装、卸载、查询、升级和校验等管理操作
- 包文件组成 (每个包独有)
- RPM包内的文件
- RPM的元数据,如名称,版本,依赖性,描述等
- 安装或卸载时运行的脚本(有些包有,有些包没有,注意恶意脚本) – 数据库(公共):/var/lib/rpm
- 可用ll /var/lib/rpm 查看
- 程序包名称及版本
- 依赖关系
- 功能说明
- 文件类型,属性信息,权限等等
- 包安装后生成的各文件路径及校验码信息
当包安装的时候,会把包内的文件按照它的路径自动拷贝到系统中,然后会生成数据库文件,把包里面文件初始安装的各种信息(上面写的那些)存入包数据库中,这样系统就可以利用包管理器从而清楚知道本机上安装了哪些包以及这些包的各种信息了
- 注意,这个数据库很重要,如果被破坏,系统就无法判断哪些包安装了,哪些包没有安装,不知道关于装的包的任何信息。不能用
rpm -q命令查询包的信息,也也无法卸载掉现在已经装的包等等各种操作都无法进行。 - 它可以用来对包进行校对工作
2.5. 程序包的来源
管理程序包的方式: 使用包管理器:rpm
使用前端工具:yum, dnf获取程序包的途径:
(1) 系统发版的光盘或官方的服务器
CentOS镜像:
https://www.centos.org/download/
http://mirrors.aliyun.com
http://mirrors.sohu.com
http://mirrors.163.com
(2) 项目官方站点
(3) 第三方组织:
Fedora-EPEL:
Extra Packages for Enterprise Linux
Rpmforge:RHEL推荐,包很全,建议使用它作为一个yum库(阿里云里面就有)
搜索引擎:(不能判定是否安全,慎用)
http://pkgs.org
http://rpmfind.net
http://rpm.pbone.net
https://sourceforge.net/
(4) 自己制作
rpmbuild,自己源码编译配置好之后自己制作rpm包,然后进行安装就行了。注意:第三方包建议要检查其合法性
来源合法性,程序包的完整性如果公司中制作yum库,最好把包全部下载下来放在自己内网服务器提供下载避免网速影响,同时yum库一定要多个。同时可把自己的光盘当做第一个本地yum库避免网络问题。
挂载光盘可用mount /dev/sr0 /mnt 命令,不过会在开机后消失,可以用 /misc/cd来挂载光盘
- 如果一直不访问 /misc/cd 它会消失掉,它是个万能自动挂载目录
- Centos7上面,需要先安装
rpm -ivh autofs(或者yum install autofs) ,然后启动功能(下次开机可启动)systemctl enable autufs, 然后立即启动此功能systemctl start autofs
3. rpm包管理
3.1. CentOS系统上使用rpm命令管理程序包:
安装、卸载、升级、查询、校验、数据库维护
3.2. 安装
rpm {-i|--install} [install-options] PACKAGE_FILE…
-v: verbose
-vv:
-h: 以#显示程序包管理执行进度
rpm -ivh PACKAGE_FILE ...
- 注意在脚本里安装只需要-i即可。
3.3. 安装的选项 (rpm -i之后再跟下面这些额外选项)
3.3.1. [install-options]
--test: 测试安装,但不真正执行安装,即dry run模式
--nodeps:忽略依赖关系,强行安装包
--replacepkgs 覆盖安装(安装好的包,不小心删除了部分文件导致缺失的时候重新安装时用此选项,避免无法重新安装的问题,也可以用--force)
--replacefiles 覆盖安装(两个不同的包有相同路径和名称的文件时进行文件覆盖安装)
--nosignature: 不检查来源合法性
--nodigest:不检查包完整性
--noscripts:不执行程序包脚本
%pre: 安装前脚本 --nopre
%post: 安装后脚本 --nopost
%preun: 卸载前脚本 --nopreun
%postun: 卸载后脚本 --nopostun
3.4. rpm包升级
rpm {-U|--upgrade} [install-options] PACKAGE_FILE...
rpm {-F|--freshen} [install-options] PACKAGE_FILE...
upgrade:安装时如果系统已经有旧版程序包,则“升级”,如果不存在旧版程序包,则“安装”
freshen:安装时如果系统已经有旧版程序包,则“升级”,如果不存在旧版程序包,则不执行升级操作
rpm -Uvh PACKAGE_FILE ...
rpm -Fvh PACKAGE_FILE ...
--oldpackage:降级
--force: 强制安装(这个更常用,常常替代--replacepkgs)
3.4.1. 升级需要注意:
(1) 不要对内核做升级操作;Linux支持多内核版本并存,因此直接安装新版本内核,开机时可以选择载入哪个内核
(2) 如果原程序包的配置文件安装后曾被修改,升级时,新版本提供的同一个配置文件不会直接覆盖老版本的配置文件,而把新版本配置文件重命名(FILENAME.rpmnew)后保留
3.5. (已经安装的)包查询
rpm {-q|--query} [select-options] [query-options] 包名
- 注意包查询只需要写包名即可,不需要写包的全部路径
3.5.1. [select-options]
-a:所有包
-f:查看指定的文件由哪个程序包安装生成
-p rpmfile:针对尚未安装的程序包文件做查询操作
--whatprovides CAPABILITY:查询指定的CAPABILITY由哪个包所提供
--whatrequires CAPABILITY:查询指定的CAPABILITY被哪个包所依赖
rpm2cpio 包文件 | cpio –tv :预览包内文件
rpm2cpio 包文件 | cpio –id "*.conf" :释放包内文件
3.5.2. [query-options]
--changelog:查询rpm包的changelog
-c:查询程序(包)的配置文件
-d:查询程序(包)的(帮助等)文档
-i:information ,查看包的本身的各种信息
-l:查看指定的程序包安装后生成的所有文件
--scripts:程序包自带的脚本
--provides:列出指定程序包所提供的CAPABILITY
-R:查询指定的(程序包所依赖的CAPABILITY
3.5.3. 常用查询用法:
-qi PACKAGE
-qf FILE(要写详细路径)
-qc PACKAGE(配置文件)
-ql PACKAGE
-qd PACKAGE (文档)
-qpi PACKAGE\_FILE
-qpl PACKAGE\_FILE, ...
-qa
3.6. 包卸载:
rpm {-e|--erase} [--allmatches] [--nodeps] [--noscripts] [--notriggers] [--test] PACKAGE_NAME ...
- 注意后面也只需要写包名即可
- 当包卸载时,对应的配置文件不会删除, 以FILENAME.rpmsave形式保留
3.7. 包校验
rpm {-V|--verify} [select-options] [verify-options] 包名
大小 S file Size differs
权限 M Mode differs (includes permissions and file type)
哈希值 5 digest (formerly MD5 sum) differs(哈希)
设备编号 D Device major/minor number mismatch
链接号 L readLink(2) path mismatch
属主 U User ownership differs
属组 G Group ownership differs
时间戳 T mTime differs
能力 P capabilities differ
- 校验就是查询已经安装好的包,与这个包刚刚新装的时候的各种元数据(存放进了数据库(/var/lib/rpm)中)差别;注意它后面直接跟包名即可
- 例如:
# chown zhang /usr/bin/tree
# rpm -V tree
.....U... /usr/bin/tree
3.8. 包来源的合法性验证及完整性验证
完整性验证:SHA256
来源合法性验证:RSA
3.8.1. 公钥加密
对称加密:加密、解密使用同一密钥
非对称加密:密钥是成对儿的
public key: 公钥,公开所有人
secret key: 私钥, 不能公开
3.8.2. 导入所需要公钥
- CentOS 7发行版光盘提供:RPM-GPG-KEY-CentOS-7; 可以用cat 打开查看
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 :导入公钥信息,类似安装rpm包 (安装光盘内也有这个文件,也可导入安装光盘内的这个文件)
rpm -qa "gpg-pubkey*" :通配符模糊查询导入之后的公钥包名字
然后再用rpm -qi gpg-pubkey(全名)查看其中内容。
rpm -e 可以删除到入之后的公钥包(和删除包一样只写包名即可)
rpm -K checksig rpmfile(要写完整路径的rpm包) :检查包的完整性和签名
- 导入公钥之后再装包就不会显示warning警报了
3.9. rpm数据库
3.9.1. 数据库重建:
/var/lib/rpm
rpm {--initdb|--rebuilddb}
initdb: 初始化
如果事先不存在数据库,则新建之
否则,不执行任何操作
rebuilddb:重建已安装的包头的数据库索引目录
-- 注意重建数据库基本上很少用到,因为都是空文件没有必要,每次包安装或者其他操作的时候自动就建立并更新了数据库
4. 更多注意点:
- 注意脚本中安装只需要- i即可
- 只有安装需要写全包的路径,查询卸载都只需要写包名
- rpm -q查询包不知道名字的情况下可用
rpm -qa |grep "regex"或者直接rpm -qa "glob"进行模糊查找- 注意利用grep正则表达式查找是包含查找,而后面的通配符方式则是全匹配方式,所以通配符的方式最好多用
*包名的部分*这种方式避免找不到 - 但是别忘记了,
rpm -q查询选项查询的是数据库中的包,也就是已经安装的包,没有安装的包是无法查询的
- 注意利用grep正则表达式查找是包含查找,而后面的通配符方式则是全匹配方式,所以通配符的方式最好多用
- 安装时
-i后选项replacepkgs命令用于同一个包,但是安装后不小心删除了包中部分文件的时候,重装这个包无法安装时的选项命令(覆盖安装的意思,也可以用--force强制安装);replacefiles命令则是为了避免两个不同的包生成同一个相同的文件路径和文件名的情况下无法安装时使用,强制覆盖掉路径相同的文件进行安装。- 注意也可以用
rpm2cpio rpm包 |cpio -id 缺失的文件\只解包解出来这个缺失的文件,然后cp到目录里,不过这个方法可能会更改cp出来的文件的权限,因此不建议这样操作
- 注意也可以用
- 默认安装包时候会安装脚本,如果为了避免安全风险可以
--noscripts - 注意包的升级会把旧版本的包给删除,因此升级要慎重.基本上不要升级,直接重新装系统和软件。
- 而关于系统linux内核,因为内核的名字每个都不相同,linux支持多内核共存,不会相互覆盖,用
--force强制安装内核rpm包即可,装好后可在boot目录下查看安装后的内核。 - 装新内核的目的就是为了用一些新的软件功能,有时候还是有必要装的。卸载的时候注意用
rpm -e kernel会提示有多个内核,因此要写全内核名。 - 而包和软件的名字都是相同的,因此再次安装的时候不能两个共存,会覆盖,所以不可能存在两个相同的软件不同的版本。
- 内核装好后开机的时候可以选择将哪个内核载入内存中,注意内核开机载入内存中之后,硬盘上的内核文件即在当前shell下不再需要了,可以删除,但是下次便无法开机了
- 而关于系统linux内核,因为内核的名字每个都不相同,linux支持多内核共存,不会相互覆盖,用
- rpm的安装也可以用网络路径,只要把路径写上即可,后面直接跟上网络的路径全名
- 用
rpm -qi 软件(包)名的方式可查询包的各种详细信息和介绍,但是前提是这个包已经安装了。如果没有安装的包无法查询,但是可以用rpm -qpi 软件(包)文件全路径名的方式查询它的信息,注意多了一个p选项,(p它表示后面必须跟上文件名,而不是包名,ql同理)- 没装的情况下也可用
rpm -qpl 包全路径名查询里面包含的所有文件,安装之后可以用rpm -ql 软件(包)名的方式查询包内的文件列表 - 原因就是,
-q查询选项是根据已经安装的包的数据库文件来查询包内信息的,所以只需写包名即可,同时这个包也必须安装在了系统上才行;而多加一个-p选项则是指向的原始的未安装的RPM包文件,对它进行查询,所以要指明RPM包的文件全路径,此时这个包装没装都无所谓啦~
- 没装的情况下也可用
- 反向查询已经安装好的系统磁盘上的文件来自于哪个包(上面第8项的查询都是查询包名,不论是安装还是未安装的)则用
rpm -qf 安装好的文件名的**全路径**,来查询它来自于那一个包。 比如上面两个命令配合使用:
1.先查询文件来自那个包:
# rpm -qf /bin/cat
coreutils-8.22-23.el7.x86_64
2.再查看包内的详细信息
# rpm -qi coreutils
- 同时注意,即使删掉了安装过的某个包里的文件(二进制,文本,帮助等等),同样可以用
rpm -qf 误删掉的文件的**全路径**来查询,原因就是因为-q只是查询的/var/lib/rpm里面的数据库记录的信息,和这个文件本身还在不在系统上没有关系。
3个capability ,两个是一对,一个可全查:
-q --whatprovides后面跟文件或者二进制程序等,查询哪个包提供了这个文件或者程序-q --provides后面跟包,显示包提供了那些能力-q --whatrequires后面既可以跟文件或者二进制等,也可以跟包,查询其他的哪些包需要这个文件或者这个包。 还有一个-qR ,后面跟包,查询这个包依赖哪些文件和capability
rpm -K 包的详细路径,检验包,倒入公钥后再装包就不会warning报警了。
留言