重点:
rpm -i -e -qi -ql -qf -qa --scripts。
yum install remove info list repolist provides。
配置系统源。
搭建私有仓库服务器。
源码编译安装。
ubuntu dpkg apt /etc/apt/sources.list。
1)软件运行和编译
Windows 和 Linux 安装软件存在一些显著的区别。主要源于两者操作系统的不同性质。
Windows 是一个闭源操作系统,大部分软件开发商提供经过编译的闭源安装包(通常是.exe文件)"毕竟基本都是商用产品,谁给你开源哟!"。这些安装包不需要用户进行编译,只需双击执行即可开始安装。
而 Linux 是一个开源操作系统,因此开发商通常提供开源软件的源代码。用户可以访问源代码,这为用户提供了更高的透明度和自定义性。
在 Linux 上,用户通常可以选择自行编译软件,以便根据自己的需求进行优化。用户需要确保系统具有所需的依赖项(库、工具等),以便成功编译和运行软件。
在 Linux 生态中,大部分软件采用 C 语言进行开发。这使得大多开源软件通常提供 C 语言源代码,需用户自行配置系统依赖环境并进行编译安装。
当然,在 Linux 系统中,为了提升用户的使用体验并简化软件安装过程,出现了软件包管理机制。企业如 Red Hat、Ubuntu 等提供了软件源项目,使用户可以通过一条命令来完成软件的安装、升级和管理。
Linux 发行版通常附带了软件包管理器,如 Debian/Ubuntu 的 APT、Red Hat/CentOS 的 YUM,以及 Arch Linux 的 Pacman。这些管理器允许用户从预配置的软件源中直接下载、安装和管理软件,无需手动编译或解决依赖项。
软件包管理器会自动处理依赖关系,确保所需的库和工具在安装时都会被满足。这极大地简化了软件安装过程,减少了用户的繁琐操作。
1.1)软件相关概念
1)ABI
**ABI :**Application Binary Interface
Windows 与 Linux 不兼容
ELF (Executable and Linkable Format)Linux
PE (Portable Executable)Windows
库级别的虚拟化:
Linux: WINE [ 在 Linux 系统中模拟 Windows ]
**Windows:**Cygwin [ 在 Windows 系统中模拟 Linux ]
2)API
API 即 Application Programming Interface "开发接口",
API 可以在各种不同的操作系统上实现给应用程序提供完全相同的接口,而它们本身在这些系统上的实现却可能迥异。
主流的操作系统有两种,一种是 Windows 系统,另一种是 Linux 系统。由于操作系统的不同,API 又分为 Windows API 和 Linux API。
在 Windows 平台开发出来的软件在 Linux 上无法运行,在 Linux 上开发的软件在 Windows 上又无法运行,这就导致了软件移植困难,POSIX 标准的出现就是为了解决这个问题。
**POSIX:**Portable Operating System Interface 可移植操作系统接口,定义了操作系统应该为应用程序提供的接口标准,是IEEE为要在各种UNIX操作系统上运行的软件而定义的一系列 API 标准的总称。
Linux 和 Windows 都要实现基本的 posix 标准,程序就在源代码级别可移植了。
3)开发语言
系统级开发
汇编
C
C++
应用级开发
Java
Python
go
php
perl
basic
ruby
bash
1.2)C 语言程序的 实现过程
C 程序源代码 >> 预处理 >> 编译 >> 汇编 >> 链接
C 语言的程序编译主要经过 四个过程:

预处理阶段(Pre-Processing)
将所有的 #define 删除,并且展开所有的宏定义。
处理所有的条件预编译指令,比如 #if #ifdef #elif #else #endif 等。
处理 #include 预编译指令,将被包含的文件插入到该预编译指令的位置。
删除所有注释 "//"和"/* */"。
添加行号和文件标识,以便编译时产生调试用的行号及编译错误警告行号。
保留所有的 #pragma 编译器指令,因为编译器需要使用它们。
编译阶段(Compiling)
编译过程就是把预处理完的文件进行一系列的词法分析,语法分析,语义分析及优化后,最后生成相应的汇编代码。
汇编阶段(Assembling)
汇编器是将汇编代码转变成机器可以执行的命令,每一个汇编语句几乎都对应一条机器指令。汇编相对于编译过程比较简单,根据汇编指令和机器指令的对照表一一翻译即可。
链接阶段(Linking)
通过调用链接器 ld 来链接程序运行需要的一大堆目标文件,以及所依赖的其它库文件,最后生成可执行文件。
1.3)示范:GCC 编译过程
// 0. 环境准备
vim hello.c
#include <stdio.h>
int main(void)
{
printf("Hello, XiaoWang!\n");
}

// 安装 gcc 编译工具
yum install gcc -y
// 1. 分步骤编译运行
// 1.1
// gcc -E hello.c -o hello.i // 对 hello.c 文件进行预处理, 生成 hello.i 文件
cat hello.i // 这个时候文件还是文本文件, 只是`文本中多了很多内容`
ll -h | grep hello // hello.i 比 hello.c 大了很多。


// 1.2 对预处理文件进行编译
// gcc -S hello.i -o hello.s // 对预处理文件进行编译, 生成了`汇编文件`
cat hello.s

// 1.3 对汇编文件进行编译
// gcc -c hello.s -o hello.o // 对汇编文件进行编译, 生成了`目标文件`
cat hello.o // 该文件已成为二进制文件。无法查看啦。


// 1.4 最后"生成二进制文件"
// gcc hello.o -o hello // 对目标文件进行链接, 生成 `可执行文件`

// 2. 或"一步实现编译过程"
// gcc hello.c -o hello // 一步实现编译过程
// 3. 验证
mv hello /usr/bin
hello

1.4)示范:NGINX 源码
[ 事实上,互联网上很多使用 C 语言写好的源码,里面并不会只有一个文件。]
举例:NGINX
https://nginx.org/en/download.html
// 下载源码包
wget https://nginx.org/download/nginx-1.24.0.tar.gz
// 解压并进入目录
tar xzvf nginx-1.24.0.tar.gz && cd nginx-1.24.0/
// 查看 NGINX 源码包中包含多少个 .c 文件
find . -name '*.c' -type f | wc -l

// 查看 NGINX 源码包中的 .c 文件总共有多少行代码
find . -name '*.c' -type f | xargs cat | wc -l

1.5)软件模块的静态和动态链接
链接 主要作用是把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确地衔接,分为 静态链接 和 动态链接。

1)静态链接
[ 静态链接 是将所有代码和库的副本复制到可执行程序中,使其独立运行。 ]
把程序对应的依赖库复制一份到包
生成模块文件libxxx.a libxxx.b
嵌入程序包
升级难,需重新编译
占用较多空间,迁移容易
2)动态链接
[ 动态链接 是在运行时通过引用加载外部库,实现共享使用,减小程序体积。 ]
只把依赖加做一个动态链接
生成模块文件 libxxx.so
连接指向
占用较少空间,升级方便
1)静态链接
优点:
独立性: 可执行文件包含所有必要的代码和库,不依赖外部文件,确保程序在任何环境下运行。
**性能:**执行速度较快,因为所有代码都在一个文件中,减少了运行时加载的开销。
**版本控制:**不受外部库版本变化的影响,代码和库的副本固定在程序中。
缺点:
体积: 可执行文件较大,占用更多存储空间,可能浪费资源。
**更新和维护:**需要重新编译整个程序才能更新库,不方便更新和修复 bug。
**共享性:**不适合多个程序共享同一库的情况,导致资源浪费。
2)动态链接<常用>
优点:
**节省空间:**可执行文件只包含对库的引用,共享库的代码在磁盘上,多个程序可以共享同一库的副本,减小程序体积。
**更新和维护:**只需替换库文件即可更新,不需要重新编译整个程序,便于维护。
**共享性:**多个程序可以共享同一库,节约系统资源。
缺点:
**启动开销:**运行时需要加载外部库,可能稍微增加程序启动时间。
**依赖性:**程序依赖于外部库文件,如果库文件缺失或版本不匹配,可能导致程序无法运行。
**移植性:**需要确保目标系统上有所需的库,可能在不同系统上存在兼容性问题。
3)模块(库)文件
// 查看二进制程序所依赖的库文件
// type ldd
// man ldd
// 查看二进制程序'所依赖的 lib 库文件'
ldd /usr/bin/ls

示范:库文件破坏后,将导致依赖的程序无法正常运行。
// 我们将 ls 命令调用的某个库文件移走
cd /lib64
mv libc.so.6 /opt
// 再次执行, 报错...
ls

// 好家伙, 移动不回去咯, mv 命令也依赖该库
mv /opt/libc.so.6 /lib64

// 目前看, 只能从其他机器拷贝一个同样的库文件过来咯...
解决方式 2:光盘救援
[ 重启计算机 ]

// 内核选项界面, 输入如下快捷键
Ctrl + Alt + Insert
// 0.5 秒内按下 ESC !!!
Esc
// 出现如下界面, 选择 CD-ROM Drive

Troubleshooting

Rescue a CentOS Linux System

Continue

sysimage

// 查看根目录
ls /mnt/sysimage
// 找到我们之前拷贝走的 libc.so.6 库文件
ls /mnt/sysimage/opt
// 在'光盘救援模式'中将库文件拷回该存在的位置
mv /mnt/sysimage/opt/libc.so.6 /lib64/
// 重启
reboot
// 管理及查看本机装载的库文件
// 加载配置文件中指定的库文件
ldconfig
// 显示本机已经缓存的所有可用库文件名及文件路径映射关系
/sbin/ldconfig --p
// 配置文件
/etc/ld.so.conf
/etc/ld.so.conf.d/*.conf
// 缓存文件
/etc/ld.so.cache
Java 程序编译运行过程


2)软件包与包管理器
2.1)软件包介绍
开源软件最初只提供了**.tar.gz**的打包的源码文件,用户必须自己编译每个想在 GNU/Linux 上运行的软件。
用户急需系统能提供一种更加便利的方法来管理这些软件,当 Debian 诞生时,这样一个管理工具 dpkg 也就应运而生,可用来管理 deb 后缀的 "包" 文件。
从而著名的 **"package"**概念第一次出现在 GNU/Linux 系统中,稍后 Red Hat 才开发自己的 rpm 包管理系统。
示范

// CentOS7
// 查看系统是否安装 autofs
// 如果未安装, 则安装 autofs
rpm -qa autofs || yum install autofs -y
// 启用服务
systemctl enable --now autofs
// 挂载
mount /dev/sr0 /misc/cd
df -h
ll /misc/cd/

在 CentOS 7 中,只有 **"Packages"**一个主要的软件仓库,用于存放所有的软件包。
du -sh *

在 CentOS 8 中,有 "BaseOS" 和**"AppStream"**两个主要的软件仓库,用于存放不同类型的软件包。
// CentOS 8
// BaseOS: 包含操作系统的核心组件和基本工具,用于支持系统的基本功能。这些软件包通常包括系统启动、硬件驱动、基本命令和实用工具等。包
// AppStream: 包含了各种应用程序、库以及用户空间工具,以满足广泛的应用需求。这些软件包可能包括办公套件、开发工具、图形界面应用程序、多媒体工具等。

rpm 软件仓库
// 全是 rpm 格式的软件包
ls Packages/

rpm 包 命名约定
zip-3.0-11.el7.x86_64.rpm
zip // 软件包名称
3.0 // 软件包版本号
11 // 打包次数, 在软件包在构建过程中可能需要多次打包,这个数字表示软件包的构建次数。
el7.x86_64.rpm // 固定格式, 指定了软件包的构建目标(el7 表示适用于 RHEL/CentOS 7)、适用的CPU架构(x86_64 表示 64 位 x86 架构)以及 RPM 包的扩展名。
yum-plugin-aliases-1.1.31-54.el7_8.noarch.rpm
yum-plugin-aliases // 软件包名称
1.1.31 // 软件包版本号
54 // 打包次数
el7_8.noarch.rpm // 固定格式
在 Ubuntu 中
// Ubuntu
apt install autofs -y
// 编辑配置文件
vim /etc/auto.master
/misc /etc/auto.misc
// 重启 autofs
systemctl restart autofs
2.2)软件包内的文件分类
二进制文件
库文件
配置文件
帮助文件
范例: 利用 cpio 工具 查看包文件列表。
// 格式
rpm2cpio 包文件 | cpio --itv 预览包内文件
rpm2cpio 包文件 | cpio --id "*.conf" 释放包内文件
// 案例
rpm2cpio tree-1.6.0-10.el7.x86_64.rpm | cpio -itv

如何基于 包管理器 安装,卸载,查询 软件包?
2.3)程序包管理器
软件包管理器功能
将编译好的应用程序的各组成文件打包一个或几个程序包文件,利用包管理器可以方便快捷地实现程序包的安装、卸载、查询、升级和校验等管理操作。
主流的程序包管理器
**Redhat:**rpm 文件, rpm 包管理器。rpm:Redhat Package Manager
**Debian:**deb 文件, dpkg 包管理器。
type rpm
file /usr/bin/rpm

2.4)包命名
源代码 打包文件命名
// name-VERSION.tar.gz|bz2|xz
linux-6.4.12.tar.xz
nginx-1.22.1.tar.gz
nginx // 源码包名称
1.2.1 // 源码包版本号
tar.gz // 打包方式
RPM 包 命名方式
zip-3.0-11.el7.x86_64.rpm
zip // 软件包名称
3.0 // 软件包版本号
11 // 打包次数, 在软件包在构建过程中可能需要多次打包,这个数字表示软件包的构建次数。
el7.x86_64.rpm // 固定格式, 指定了软件包的构建目标(el7 表示适用于 RHEL/CentOS 7)、适用的CPU架构(x86_64 表示 64 位 x86 架构)以及 RPM 包的扩展名。
yum-plugin-aliases-1.1.31-54.el7_8.noarch.rpm
yum-plugin-aliases // 软件包名称
1.1.31 // 软件包版本号
54 // 打包次数
el7_8.noarch.rpm // 固定格式
常见的 arch 架构
x86: i386, i486, i586, i686
x86_64: x64, x86_64, amd64
powerpc: ppc
跟平台无关:noarch
范例
bash-3.2-32.el5_9.1.i386.rpm
bash-4.2.46-19.el7.x86_64.rpm
bash-4.4.19-7.el8.x86_64.rpm
bash-4.4.19-7.el8.aarch64.rpm
bash-4.4.19-7.el8.ppc64le.rpm
bc_1.07.1-2_amd64.deb
bc_1.07.1-2_s390x.deb
**范例:**统计 rpm 的架构类型及相应的包数量
cd /misc/cd/BaseOS/Packages
// 牛方法
-
ls *.rpm | rev | cut -d. -f2 | rev | sort | uniq -c // rev
-
ls *.rpm | sed -rn 's/.*\.([^.]+)\.rpm$/\1/p' | sort | uniq -c // sed -rn
-
ls *.rpm | grep -Eo '[^.]+\.rpm$'| grep -Eo
'^[^.]+' | sort | uniq -c
- ls *.rpm | grep -Eo '[^.]+\.rpm$' | cut -d. -f1| sort | uniq
-c
// 傻方法
ls *.rpm | grep i686 | wc -l
ls *.rpm | grep noarch | wc -l
ls *.rpm | grep x86_64 | wc -l



2.5)分类和拆包
软件包为了管理和使用的便利,会将一个大的软件分类,放在不同的子包中。
分类
Application-VERSION-ARCH.rpm: 主包
Application-devel-VERSION-ARCH.rpm:开发子包
Application-utils-VERSION-ARHC.rpm:其它子包
Application-libs-VERSION-ARHC.rpm:其它子包
cd Packages/
ll httpd*

案例 1
[ **这样细分的好处是什么呢?**早期的操作系统就一个包,你可能只想安装其中的 tools 工具,那不行,要安装就全安装了。现在细分了,那就你想只安装其中的 tools ,就安装指定的工具包即可。]
通过细分软件包,你可以更精细地选择安装你需要的功能和工具。
在早期的操作系统中,你只能选择全部安装或者不安装。而现在,通过细分软件包,你可以根据自己的需求选择性安装特定功能,避免了不必要的资源浪费。
httpd-2.4.6-95.el7.centos.x86_64.rpm主包
httpd-devel-2.4.6-95.el7.centos.x86_64.rpm开发包
httpd-manual-2.4.6-95.el7.centos.noarch.rpm手册包
httpd-tools-2.4.6-95.el7.centos.x86_64.rpm工具包
案例 2
[ ibus 输入法 ,有五笔有拼音,通过软件包细分即可仅安装其中的某一个功能项。]
ls ibus*

2.6)包依赖
软件包之间可能存在依赖关系,甚至循环依赖:A包依赖B包,B包依赖C包,C包依赖A包。
安装软件包时,会因为缺少依赖的包,而导致安装包失败。
解决依赖包管理工具:
yum:rpm 包管理器的前端工具。
dnf:Fedora18 + rpm 包管理器前端管理工具,CentOS 8 版代替 yum
apt:deb 包管理器前端工具。
zypper:suse 上的rpm前端管理工具。
2.7)程序包管理器相关文件
包文件组成(每个包独有)
包内的文件。
元数据,如:包的名称,版本,依赖性,描述等。
postinstall 可能会有包安装或卸载时运行的脚本。
数据库(公共):/var/lib/rpm
程序包名称及版本
依赖关系
功能说明
包安装后生成的各文件路径及校验码信息
示例 1 :postinstall
< Linux 小技巧 >
// 查询 RPM 包中的脚本信息
// 帮助你了解在安装、卸载或升级这个包时,会执行哪些脚本操作,以及这些操作的具体内容。
rpm -qp --scripts httpd-2.4.6-95.el7.centos.x86_64.rpm
// "解析"
preinstall scriptlet # 代表安装前执行脚本
postinstall scriptlet # 代表安装后执行脚本
preuninstall scriptlet # 代表卸载前执行脚本
postuninstall scriptlet # 代表卸载后执行脚本

在过去,曾出现过一些恶意的 RPM 包 ,其中开发者在软件包安装后执行的postinstall 脚本中故意编写了具有破坏性的命令 ,例如**"rm -rf /"** 。这样的行为令人震惊,因为这些命令可能导致系统遭受严重影响,甚至引发严重的数据丢失和系统崩溃。
**这种情况凸显了在安装软件包之前仔细审查其内容的重要性。**用户在执行安装操作之前,必须保持高度警惕,确保所要安装的软件包来自可信任的来源。
示例 2 :/var/lib/rpm
用于存储 RPM 包管理器 (RPM Package Manager) 在系统中安装的软件包数据库和元数据。
数据库文件: 一个名为 Packages 的数据库文件
该文件记录了系统中安装的所有 RPM 软件包的信息,包括软件包的名称、版本、文件列表、依赖关系等。
这个数据库使得 RPM 能够有效地跟踪系统中安装的软件包,帮助进行升级、查询和管理。
事务日志: 一个名为 __db.xxx 的文件
其中 xxx 是文件格式的标识符。
这些文件用于记录 RPM 数据库的事务日志,以便在安装、卸载或升级软件包时保持一致性。
其他元数据: /var/lib/rpm 目录可能还包含其他元数据文件。
用于存储 RPM 软件包的附加信息,如签名、已安装文件列表、脚本等。
总之,/var/lib/rpm 是 RPM 包管理器的 核心部分,存储了与软件包管理相关的重要信息。
这个目录的存在使得系统能够跟踪已安装的软件包,并在需要时执行软件包的各种操作。尽管这个目录对系统的正常运行至关重要,但一般情况下,用户不需要直接操作或修改其中的内容。
ll /var/lib/rpm

2.8)获取程序包的途径
软件包需要事先将源码进行编译后打包形成,获取包的途径如下:
1)系统发版的光盘或官方网站
CentOS 镜像:
https://www.centos.org/download/
https://mirrors.huaweicloud.com/
https://mirror.tuna.tsinghua.edu.cn/
Ubuntu 镜像:
http://cdimage.ubuntu.com/releases/
2)第三方组织提供
EPEL 源: 一个社区驱动的项目,旨在为企业级 Linux 发行版(如 CentOS、RHEL)提供额外的软件包。
这些软件包不包含在原始发行版的官方软件仓库中,但是可以为系统管理员和用户提供更多的功能和工具。
Fedora-EPEL :Extra Packages for Enterprise Linux。
https://fedoraproject.org/wiki/EPEL
https://mirrors.aliyun.com/epel/
https://mirrors.cloud.tencent.com/epel/
Rpmforge:官网:http://repoforge.org/, RHEL推荐,包很全,即将关闭。
Community Enterprise Linux Repository:http://www.elrepo.org,支持最新的内核和硬件相关包。[ 后续升级系统内核给大家演示。]
阿里源: https://mirrors.aliyun.com/


腾讯源: https://mirrors.cloud.tencent.com/


3)软件项目官方站点
http://yum.mariadb.org/10.4/centos8-amd64/rpms/
http://repo.mysql.com/yum/mysql-8.0-community/el/8/x86_64/

4)搜索引擎
**注意:**第三方包建议要检查其合法性,来源合法性,程序包的完整性。
5)自己制作
将源码文件,利用工具。**如:**rpmbuild,fpm 等工具制作成 rpm 包文件。