7.11 Linux源码包安装和卸载
- 由于 Linux 操作系统开放源代码,因此在其上安装的软件大部分也都是开源软件,例如 Apache、Tomcat 和PHP等。开源软件基本都提供源码下载,可采用源码安装的方式安装软件。
注意,这次使用的源码包,指的是软件所有源代码的压缩包,其后缀名为 “.tar.gz” 或 “.tar.bz2”;而 SRPM 源码包本质上属于 RPM 包,也就是源码的RPM包,其文件后缀为 “.src.rpm”。虽然都叫源码包,但不是一码事。
-
软件的源代码,也就是软件的原始数据,任何人都可以通过源代码查看该软件的设计架构和实现方法,但软件源代码无法再计算机中直接运行安装,需要将源代码通过编译转换为计算机可以识别的机器语言,然后才可以安装。
-
Linux 系统中,绝大多数软件的源代码都是用 C 语言编写的,少部分用C++(或其他语言)编写。因此要想安装源码包,必须安装 gcc 编译器(如果涉及 C++ 源码程序,还需要安装 gcc-c++)。安装 gcc 之前,可先使用如下命令看看是否已经安装:
[root@CncLucZK ~]# rpm -qa gcc
gcc-8.2.1-3.5.el8.x86_64
[root@CncLucZK ~]# rpm -qa|grep gcc
libgcc-8.2.1-3.5.el8.x86_64
gcc-8.2.1-3.5.el8.x86_64
如果未安装,考虑到安装 gcc 所依赖的软件包太多,推荐使用 yum 安装 gcc
-
除了安装编译器,还需要安装 make 编译命令。要知道,编译源码包可不像编译一个 hello.c 文件那样轻松,包中含大量的源码文件,且文件之间有着非常复杂的关联,直接决定着各文件编译的先后顺序,因此手动编译费时费力,而使用 make 命令可以完成对源码包的自动编译。
-
同样,在安装 make 命令之前,可使用如下命令查看其是否已经安装:
[root@CncLucZK httpd-2.4.54]# rpm -qa make
make-4.2.1-9.el8.x86_64
- 如果未安装,可使用
yum -y install make
命令直接安装 make。
7.11.1 Linux源码包安装软件
- 以安装 apache 为例,安装过程分为如下几步:
- 下载 apache 源码包。该软件的源码包可通过官方网站 http://httpd.apache.org/download.cgi#apache24 或https://downloads.apache.org/httpd/#mirrors下载,得到的源码包格式为压缩包( “.tar.gz” 或 “.tar.bz2” )。
由Linux文件目录结构一节可知:将各种文件分门别类保存在对应的目录中,成为约定俗成的习惯。Linux 系统中用于保存源代码的位置主要有 2 个,分别是 “/usr/src” 和 “/usr/local/src”,其中 “/usr/src” 用来保存内核源代码,“/usr/local/src” 用来保存用户下载的源代码。
2.将源码包进行解压缩,使用命令如下
[root@CncLucZK ~]#tar -zxvf httpd-2.4.54.tar.gz|more
3.进入解压目录,执行如下命令
[root@CncLucZK ~]# cd httpd-2.4.54
- ./configure 软件配置与检查。这一步主要完成以下 3 项任务:
- 检测系统环境是否符合安装要求。
- 定义需要的功能选项。通过 “./configure–prefix=安装路径” 可以指定安装路径。注意,configure 不是系统命令,而是源码包软件自带的一个脚本程序,所以必须采用 “./configure” 方式执行(“./” 代表在当前目录下)。
- “./configure” 支持的功能选项较多,可执行 “./configure–help” 命令查询其支持的功能,例如:
[root@CncLucZK httpd-2.4.54]#./configure --help|more
#查询apache支持的选项功能(不是必需步骤)
-
- 把系统环境的检测结果和定义好的功能选项写入 Makefile 文件,因为后续的编译和安装需要依赖这个文件的内容。
此步具体执行代码如下:
[root@CncLucZK httpd-2.4.54]# ./configure --prefix=/usr/local/apache2 --prefix 选项的含义为指定安装目录。
checking for chosen layout...Apache
checking for working mkdir -p…yes
checking build system type...i686-pc-linux-gnu
checking host system type...i686-pc-linux-gnu
checking target system typa...i686-pc-linux-gnu
…省略部分输出…
此命令没有加载其他功能,只是指定安装目录。需要说明的是,“/usr/local/apache2” 目录不需要手工建立,安装完成后会自动建立(这个目录是否生成也是检测软件是否正确安装的重要标志)。
5.make 编译。make 会调用 gcc 编译器,并读取 Makefile 文件中的信息进行系统软件编译。编译的目的就是把源码程序转变为能被 Linux 识别的可执行文件,这些可执行文件保存在当前目录下。执行的编译命令如下.编程过程较为耗时。
[root@CncLucZK httpd-2.4.54]# make
6.正式开始安装软件,这里通常会写清程序的安装位置,如果没有,则建议读者把安装的执行过程保存下来,以备将来删除软件时使用。安装指令如下:
[root@CncLucZK httpd-2.4.54]# make install
- 整个过程不报错,即为安装成功。安装源码包过程中,如果出现“error”(或“warning”)且安装过程停止,表示安装失败;反之,如果仅出现警告信息,但安装过程还在继续,这并不是安装失败,顶多使软件部分功能无法使用。
注意,如果在 “./configure” 或 “make” 编译中报错,则在重新执行命令前一定要执行
make clean
命令,它会清空 Makefile 文件或编译产生的 “.o” 头文件。
7.11.2 Linux源码包卸载
- 通过源码包方式安装的各个软件,其安装文件独自保存在 /usr/local/ 目录下的各子目录中。例如,apache 所有的安装文件都保存在 /usr/local/apache2 目录下。这就为源码包的卸载提供了便利。源码包的卸载,只需要找到软件的安装位置,直接删除所在目录即可,不会遗留任何垃圾文件。需要读者注意的是,在删除软件之前,应先将软件停止服务。
- 以删除 apache 为例,只需关闭 apache 服务后执行如下命令即可:
[root@CncLucZK ~]# rm -rf /usr/local/apache2/
7.12 Linux源码包快速升级
- Linux 系统中更新用源码包安装的软件,除了卸载重装这种简单粗暴的方法外,还可以下载补丁文件更新源码包,用新的源码包重新编译安装软件。比较两种方式,后者更新软件的速度更快。
使用补丁文件更新源码包,省去了用 ./configured 生成新的 Makefile 文件,还省去了大量的编译工作,因此效率更高。
7.12.1 Linux补丁文件的生成和使用
- Linux 系统中可以使用 diff 命令对比出新旧软件的不同,并生成补丁文件。diff 命令基本格式为:
[root@localhost ~]# diff 选项 old new #比较old和new文件的不同
-
此命令中可使用如下几个选项:
- -a:将任何文档当作文本文档处理;
- -b:忽略空格造成的不同;
- -B:忽略空白行造成的不同;
- -I:忽略大小写造成的不同;
- -N:当比较两个目录时,如果某个文件只在一个目录中,则在另一个目录中视作空文件;
- -r:当比较目录时,递归比较子目录;
- -u:使用同一输出格式;
-
从生成补丁文件,到使用其实现更新软件的目的,下面我们自己创建两个文件(分别模拟旧软件和新软件),通过对比新旧文件生成补丁文件,最后利用补丁文件更新旧文件,具体步骤如下:
- 创建两个文件,执行如下命令:
[root@CncLucZK test]# cat demoold.txt
hello world 1!
hello world 2!
hello world 3!
hello world 4!
hello world 5!
hello world 6!
[root@CncLucZK test]# sed -i 's/world/linux/g' demonew.txt
hello linux 1!
hello linux 2!
hello linux 3!
hello linux 4!
hello linux 5!
hello linux 6!
2.利用 diff 命令,比较两个文件(demoold.txt 和 demonew.txt)的不同,并生成补丁文件(txt.patch),执行代码如下:
[root@CncLucZK test]# diff -Naur demoold.txt demonew.txt > differ.patch
[root@CncLucZK test]# cat differ.patch
#旧文件
--- demoold.txt 2022-10-13 18:56:30.001597669 +0800
#新文件
+++ demonew.txt 2022-10-13 20:06:35.491676677 +0800
@@ -1,6 +1,6 @@
-hello world 1!
-hello world 2!
-hello world 3!
-hello world 4!
-hello world 5!
-hello world 6!
+hello linux 1!
+hello linux 2!
+hello linux 3!
+hello linux 4!
+hello linux 5!
+hello linux 6!
#后一个文件比前一个文件多行(用+表示)
3.利用补丁文件 txt.patch 更新 old.txt 旧文件,实现此步操作需利用 patch 命令,该命令基本格式如下:
[root@CncLucZK test]# patch -pn < 补丁文件 #按照补丁文件进行更新
-pn 选项中,n 为数字(例如 p1、p2、p3 等),pn 表示按照补丁文件中的路径,指定更新文件的位置。这补丁文件是要打入旧文件的,但是当前所在目录和补丁文件中记录的目录不一定是匹配的,需要 “-pn” 选项来同步两个目录。
例如,当前位于 “/root/test/” 目录下(要打补丁的旧文件就在当前目录下),补丁文件中记录的文件目录为 “/root/test/demoold.txt”,如果写入 “-p1”(在补丁文件目录中取消一级目录),那么补丁文件会打入 “root/test/root/test/demoold.txt” 文件中,这显然是不对的;如果写入的是 “-p2”(在补丁文件目录中取消二级目录),补丁文件会打入 “/root/test/test/demo.txt” 文件中,这显然也不对。如果写入的是 “-p3”(在补丁文件目录中取消三级目录),补丁文件会打入 “/root/test/demo.txt” 文件中,demo.txt 文件就在这个目录下,所以应该用 “-p3” 选项。
如果当前所在目录是 “/root/” 目录呢?因为补丁文件中记录的文件目录为 “/root/test/old.txt”,所以这里就应该用 “-p2” 选项(代表取消两级目录),补丁打在当前目录下的 “test/old.txt” 文件上。
-
因此,-pn 选项可以这样理解,即想要在补丁文件中所记录的目录中取消几个 “/”,n 就是几。去掉目录的目的是和当前所在目录匹配。
-
现在更新 “demoold.txt” 文件,命令如下:
[root@CncLucZK test]# patch -p0< differ.patch
patching file demoold.txt
[root@CncLucZK test]# cat demoold.txt
hello linux 1!
hello linux 2!
hello linux 3!
hello linux 4!
hello linux 5!
hello linux 6!
期间可能会报一个错误:-bash: patch: command not found,说明patch包没有安装需要先安装patch包
[root@CncLucZK test]# yum -y install patch
- 可以看到,通过使用补丁文件 txt.patch 对旧文件进行更新,使得旧文件和新文件完全相同。
- 通过这个例子,明白以下两点:
- 给旧文件打补丁依赖的不是新文件,而是补丁文件,所以即使新文件被删除也没有关系。
- 补丁文件中记录的目录和当前所在目录需要通过 “-pn” 选项实现同步,否则更新可能失败。
7.12.2 给apache打入补丁
- 以 apache 为例,通过从官网上下载的补丁文件 “mod_proxy_ftp_CVE-2008-2939.diff”,更新 httpd-2.2.9 版本的 apache。
这里使用的补丁文件,修补了 apache 代理 FTP 站点时,模块空指针引用拒绝服务攻击的漏洞
- 具体更新步骤如下:
- 从 apache 官网上下载补丁文件;
- 复制补丁文件到 apache 源码包解压目录中,执行命令如下:
[root@CncLucZK ~]# cp mod_proxy_ftp_CVE-2008-2939.diff httpd-2.2.9
- 给旧 apache 打入补丁,具体执行命令如下:
[root@CncLucZK ~]# cd httpd-2.2.9
#进入apache源码目录
[root@CncLucZK httpd-2.2.9]# cat mod_proxy_ftp_CVE-2008-2939.diff
#查看补丁文件
--modules/proxy/mod_proxy_ftp.c (Revision 682869)
+ + + modules/proxy/mod_proxy_ftp.c (Revision 682870)
…省略部分输出…
#查看一下补丁文件中记录的目录,以便一会儿和当前所在目录同步
[root@CncLucZK httpd-2.2.9]# patch - p0 < mod_proxy_ftp_CVE-2008-2939.diff
#打入补丁
为什么是 “-p0” 呢?因为当前在 “/root/httpd-2.2.9” 目录中,但补丁文件中记录的目录是 “modules/proxy/mod_proxy_ftp.c”,就在当前所在目录中,因此一个 “/” 都不需要去掉,所以是 “-p0”。
- 重新编译 apache 源码包,执行如下命令:
[root@CncLucZK httpd-2.2.9]# make
5.安装 apache,执行如下命令
[root@CncLucZK httpd-2.2.9]# make install
- 通过对比上节安装源码包的过程,不难发现,打补丁更新软件的过程比安装软件少了 “./configure” 步骤,且编译时也只是编译变化的位置,编译速度更快。
注意,如果未安装过 httpd-2.2.9,就需要先打入补丁,再依次执行 "./configure"、"make"、
"make install" 命令。
- patch 命令不仅可以给就文件打入补丁,还可以执行反操作,即恢复用补丁文件修改过的源文件,例如:
[root@CncLucZK httpd-2.2.9]# patch -R < modjDroxy_ftp_CVE-2008-2939.diff
-R(大写)选项表示还原补丁。
参考文献:
Linux源码包安装和卸载教程