Linux软件安装管理之--源码包安装

2020-05-21 00:02:18 浏览数 (1)

Linux 软件安装管理之--源码包安装

 在 Windows 系统中的应用程序大多是闭源软件,这些软件的开发商在发行软件前会将软件编译为二进制软件,用户一般只能通过软件提供的安装程序进行安装。

在 Linux 系统中大多数的应用程序都是开源软件,主要开源协议有 GNU GPL、BSD 等等,Linux 上面的软件几乎都是经过 GPL 授权,所以每个软件几乎均提供源代码,你可以自行修改该程序代码以符合你个人需求。

1 源码包安装的优缺点

源码包的优点: 1)安装灵活(可以安装指定版本、指定编译参数、指定安装位置) 2)卸载方便 源码包的缺点: 1)安装步骤繁琐(步骤较多,容易出现拼写错误,需要处理复杂的依赖关系)

2 什么是开放源码、编译程序与可执行文件?

Linux 系统真正认识的可执行文件就是二进制文件(binary program)二进制文件包无需编译,可以直接执行安装使用,比如 /bin/top ,/usr/bin/passwd 这些文件就是二进制文件。

二进制文件判断命令:file

代码语言:javascript复制
[root@web ~]# file /bin/bash
/bin/bash: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=7e644dee920bc3ba797c38e05383286563712b49, stripped
[root@web ~]# file /etc/init.d/network 
/etc/init.d/network: Bourne-Again shell script, ASCII text executable

注:如果是 binary 而且是可执行的时候,就会显示执行文件类别(ELF 64-bit LSB executable),同时说明是否使用动态函式库(share libs),如果是 script 就会显示 text executables。network 的数据显示 shell script 是因为该文件第一行 #!/bin/bash 的原因,如果删除第一行,那么显示的是 ASCII 文本文件的信息。

程序代码文件一般都是纯文本文档,在完成原始代码文件的编写之后,需要将这个文件编译成为系统看的东的 binary program,要编译自然就需要经过 gcc 编译器环境编译才能运行。

gcc 编译器进行程序编译流程图:

C 语言的原始代码文件通常以 *.c 作为扩展名,在编译的过程当中还会产生所谓的目标文件(object file),这些文件以 *.o  的扩展名存在。此外,有的时候,我们会在程序当中“引用、呼叫”其他的外部子程序,或者是利用其他软件提供的“函数功能”,这个时候,我们就必须要在编译的过程中,将该函式库加进来,如此一来,编译程序就可以将所有的程序代码与函式库作一个连结(Link)以产生正确的执行文件。

小结:

开放源码:就是程序代码,写给人类看的程序语言,但机器不认识,无法直接执行,需要经过编译成为二进制才能执行‘;

编译程序:将程序代码转译成为机器看懂的语言,类似翻译者角色;

可执行文件:经过编译程序成二进制程序后,机器看懂所以可以执行的文件。

2.1 configure、make、make install 的作用和区别

configure 一般用来生成 Makefile(or makefile),makefile 记录了原始代码如何编译的详细信息,可以通过在 configure 后加上参数对安装进行控制,你如代码:

  ./configure --prefix=/usr

注:有的还可以通过指定 --sys-config= 参数进行设定,还可以加上- -whit、--enable、without、--disable 等等参数对编译加以控制,主要通过 ./configure --help 查看帮助手册。

make 是 Linux 开发套件里面自动化编译的一个控制程序,make 通过 makefile 的定义,呼叫源代码、函式库、编译器来编译,它由 makefile 设置文件提供相关的功能,比如 make install、make uninstall 来进行安装或卸载,不加参数就是默认进行源代码编译,

make 会自动判断 makefile 文件是否改动来自动更新软件。

make install 就是进行安装,它也从 makefile 中读取指令,安装到指定位置。

2.2 主、子程序的调用和链接

 编写一个主程序去调用另一个子程序:

代码语言:javascript复制
[root@web c_program]# vim thanks.c

#include <stdio.h>

int main()
{

    printf("Hello World!n");
    thanks_2(); // 调用子程序
}

[root@web c_program]# vim thanks_2.c

#include <stdio.h>

thanks_2()
{
    printf("Thank you!,I'm thanks_2...n");
}

程序的编译与连接(link)

代码语言:javascript复制
[root@web c_program]# gcc -c thanks.c thanks_2.c  //编译成为可执行的 binary file
[root@web c_program]# ll
total 16
-rwxr-xr-x 1 root root   76 May  9 09:14 thanks_2.c
-rw-r--r-- 1 root root 1520 May  9 09:27 thanks_2.o
-rwxr-xr-x 1 root root   95 May  9 09:27 thanks.c
-rw-r--r-- 1 root root 1560 May  9 09:27 thanks.o
[root@web c_program]# gcc -o thanks thanks.o thanks_2.o
[root@web c_program]# ./thanks
Hello World!
Thank you!,I'm thanks_2...

注:由于源代码文件有时并非只有一个文件,所以无法直接进行编译,这个时候需要先产生目标文件,然后再连结制作成为 binary  可执行文件。另外如果以后需要更新 thanks_2 文件内容,则只要重新编译 thanls_2.c 来产生新的 thanks_2.o,然后再连结出新的 binary 可执行文件。

3 源码包安装的基本步骤

1)下载程序源码包:保存在你的数据目录,进行解压缩;

2)查阅步骤流程:一般是 INSTALL/README 等相关文件;

3)执行configure/config:目的是检测系统环境兼容性、依赖软件等,并建立 makefile 文件;

4)make 编译:make 程序使用 makefile 作为参数配置文件,编译成为可执行文件;

5)make install 安装:make 以 makefile 这个参数配置文件,依据 install 这个目标(target)安装到指定路径。

注:如果 configure 没有指定 --prefix=/path 参数,通常默认安装在 /usr/local,建议安装位置指  /usr/local/program_name,方便以后管理。

另外:make 其它常用命令参数说明

make clean:清除上次 make 命令所产生的 object 文件(后缀为“.o”的文件)及可执行文件。

make -j4:启用 4 个 cpu 去编译,提高编译速度。

4 源码软件的升级与卸载

如果你安装时候指定的路径为: --prefix=/usr/local/xxx,把这个文件夹删除就可以,因为该软件安装的所有文件都是放置在 /usr/local/xxx 这个文件夹。

但如果你进行源码包安装的时候没有指定位置(默认值一般为 /usr/local/ ),或指定的位置为 --prefix=/usr/local,则这时候你安装软件生成的文件将分别存储在 /usr/local/ 里面的 bin、lib 或 ect 等目录中,这时候卸载起来就相对麻烦一点了

软件升级一般跟安装的步骤一样,进行检测、编译、安装。

5 源码包安装实例

一个简单实例:源码包安装 nginx

代码语言:javascript复制
[root@localhost ~]# cat /etc/redhat-release ; uname -r    // 了解系统信息
CentOS Linux release 7.7.1908 (Core)
5.6.2-1.el7.elrepo.x86_64
[root@localhost ~]# yum -y install pcre-devel openssl openssl-devel gcc gcc-c   make wget    // 安装相关依赖软件
[root@localhost ~]# cd /data/src    
[root@localhost src]# wget http://nginx.org/download/nginx-1.16.0.tar.gz     // 下载源码包
[root@localhost src]# tar xf nginx-1.16.0.tar.gz   // 解压源码包
[root@localhost src]# ls
nginx-1.16.0  nginx-1.16.0.tar.gz
[root@localhost src]# cd nginx-1.16.0    // 切换源码目录
[root@localhost nginx-1.16.0]# ls   // 编译安装前,先阅览一遍README文件,或者执行 ./configure --help 查看可配置参数
auto  CHANGES  CHANGES.ru  conf  configure  contrib  html  LICENSE  man  README  src
[root@localhost nginx-1.16.0]# ./configure --prefix=/usr/local/nginx-1.16.0     // 开始建立 makefile
checking for OS
   Linux 5.6.2-1.el7.elrepo.x86_64 x86_64
checking for C compiler ... found       // 可以看到在检测 C 编译器
   using GNU C compiler
   gcc version: 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) 
checking for gcc -pipe switch ... found
..部分省略...
creating objs/Makefile    // 可以看到成功建立起 makefile
..部分省略...
[root@localhost nginx-1.16.0]# make -j4    // make 编译,加了j4参数,非常快
[root@localhost nginx-1.16.0]# make install // make install 安装
[root@localhost nginx-1.16.0]# /usr/local/nginx-1.16.0/sbin/nginx -c /usr/local/nginx-1.16.0/conf/nginx.conf  // 启动 nginx
[root@localhost nginx-1.16.0]# curl -I http://127.0.0.1    //访问测试
HTTP/1.1 200 OK
Server: nginx/1.16.0
Date: Sun, 10 May 2020 02:33:32 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Sun, 10 May 2020 02:32:17 GMT
Connection: keep-alive
ETag: "5eb767b1-264"
Accept-Ranges: bytes

注:下载 nginx 源码包官网地址:http://nginx.org/en/download.html 或 http://nginx.org/download/

6 函式库管理 

维基百科对函式库解释:执行程序根据更新后的库信息调用库中的函数或引用库中的数据。

在我们的 Linux 操作系统当中,函式库是很重要的一个项目。 因为很多的软件之间都会互相取用彼此提供的函式库来进行特殊功能的运作, 例如很多需要验证身份的程序都习惯利用 PAM 这个模块提供的验证机制来实作,而很多网络联机机制则习惯利用 SSL 函式库来进行联机加密的机制。函式库分为静态(Static) 与动态 (Dynamic) 函式库。

6.1 静态与动态函式库

静态于动态函式库的特点与区别:

特点与区别

静态函式库

动态函式库

扩展名

后缀为 .a通常为 libxxx.a 类型

后缀为 .so通常为 libxxx.so

编译行为

整合在一块生成可执行程序可执行文件太大、消耗系统资源

函式库由执行程序读取调用函式库不能被删除、移动、重命名等执行程序文件较小

独立执行的状态

可以独立执行,不需要向外部读取函式库

不可独立执行,需要读取外部函式库

升级难易度

重新编译整个执行程序

升级函式库

注:绝大多数的函式库存放在 /lib64,/lib 目录下;kernel 的函式库存放在 /lib/modules ,不同版本的系统内核提供的函式库差异很大,所以 kernel 2.4.xx 不能换成 kernel 2.6.xx 的函式库。

6.2 ldconfig:动态库管理命令

ldconfig 命令的用途主要是在默认搜寻目录 /lib 、/lib64 、/usr/lib 以及动态库配置文件 /etc/ld.so.conf 内所列的目录下,搜索出可共享的动态链接库(格式如lib.so),进而创建出动态装入程序(ld.so)所需的连接和缓存文件。缓存文件默认为 /etc/ld.so.cache 。

代码语言:javascript复制
[root@web ~]# whereis ldconfig
ldconfig: /usr/sbin/ldconfig
[root@web ~]# rpm -qf /usr/sbin/ldconfig     // 可以看到该程序来源GNU的libc库
glibc-2.17-292.el7.x86_64
[root@web ~]# ldconfig -p | head -5    // 显示存储在当前缓存中的目录和库列表。
505 libs found in cache `/etc/ld.so.cache'
    p11-kit-trust.so (libc6,x86-64) => /lib64/p11-kit-trust.so
    libz.so.1 (libc6,x86-64) => /lib64/libz.so.1
    libz.so (libc6,x86-64) => /lib64/libz.so
    libyaml-0.so.2 (libc6,x86-64) => /lib64/libyaml-0.so.2
[root@web ~]# ldconfig -v | head    // 显示正在扫描的目录及搜索到的动态链接库,还有它所创建的连接的名字
ldconfig: Can't stat /libx32: No such file or directory
ldconfig: Path `/usr/lib' given more than once
ldconfig: Path `/usr/lib64' given more than once
ldconfig: Can't stat /usr/libx32: No such file or directory
/usr/lib64//bind9-export:
    libisc-export.so.169 -> libisc-export.so.169.0.3
    libisccfg-export.so.160 -> libisccfg-export.so.160.2.1
    libirs-export.so.160 -> libirs-export.so.160.0.5
    libdns-export.so.1102 -> libdns-export.so.1102.1.2
/usr/lib64/dyninst:
    libcommon.so.9.3 -> libcommon.so.9.3.1
    libdyninstAPI.so.9.3 -> libdyninstAPI.so.9.3.1
    libsymtabAPI.so.9.3 -> libsymtabAPI.so.9.3.1
    libinstructionAPI.so.9.3 -> libinstructionAPI.so.9.3.1
[root@web ~]# cat /etc/ld.so.conf    // 指向ld.so.conf.d目下的所有*.conf配置文件
include ld.so.conf.d/*.conf
[root@web ~]# ls /etc/ld.so.conf.d/
bind-export-x86_64.conf  dyninst-x86_64.conf  kernel-3.10.0-1062.9.1.el7.x86_64.conf  kernel-3.10.0-957.21.3.el7.x86_64.conf  mariadb-x86_64.conf
[root@web ~]# cat /etc/ld.so.conf.d/mariadb-x86_64.conf     // 可以看到该配置文件指定Mariadb数据库函式库目录/usr/lib/mysql
/usr/lib64/mysql
[root@web ~]# ll /usr/lib64/mysql
total 3068
lrwxrwxrwx  1 root root      24 Dec 16 22:47 libmysqlclient.so.18 -> libmysqlclient.so.18.0.0
-rwxr-xr-x  1 root root 3135712 Aug  8  2019 libmysqlclient.so.18.0.0
drwxr-xr-x. 2 root root    4096 Dec 16 22:47 plugin

6.3 ldd:显示程序或库文件所依赖的共享库

ldd 可以判断某个可执行的 binary 文件含有哪些动态函式库

代码语言:javascript复制
[root@web ~]# ldd --help    // ldd 帮助信息
Usage: ldd [OPTION]... FILE...
      --help              print this help and exit
      --version           print version information and exit
  -d, --data-relocs       process data relocations
  -r, --function-relocs   process data and function relocations
  -u, --unused            print unused direct dependencies
  -v, --verbose           print all information

For bug reporting instructions, please see:
<http://www.gnu.org/software/libc/bugs.html>.
[root@web ~]# ldd /usr/sbin/useradd        // 显示 /usr/bin/passwd 程序含有的动态函式库
    linux-vdso.so.1 =>  (0x00007ffeb9254000)
    libaudit.so.1 => /lib64/libaudit.so.1 (0x00007f4cbbe5f000)
    libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f4cbbc38000)
    libsemanage.so.1 => /lib64/libsemanage.so.1 (0x00007f4cbb9f7000)
    libacl.so.1 => /lib64/libacl.so.1 (0x00007f4cbb7ee000)
    libattr.so.1 => /lib64/libattr.so.1 (0x00007f4cbb5e9000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f4cbb21b000)
    libcap-ng.so.0 => /lib64/libcap-ng.so.0 (0x00007f4cbb015000)
    libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f4cbadb3000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007f4cbabaf000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f4cbc2b1000)
    libsepol.so.1 => /lib64/libsepol.so.1 (0x00007f4cba911000)
    libbz2.so.1 => /lib64/libbz2.so.1 (0x00007f4cba701000)
    libustr-1.0.so.1 => /lib64/libustr-1.0.so.1 (0x00007f4cba4cd000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f4cba2b1000)

 强行总结

在 Linux 系统当中,最标准的 C 语言编译程序为 gcc ; 在编译的过程当中,可以藉由其他软件提供的函式库来使用该软件的相关机制与功能; 一般而言,源码安装软件,最好需要 gcc, make, autoconfig 等前驱软件才行,所以在安装 Linux 之初,最好就能够选择 Software development 以及 kernel development 之类的群组; 函式库有动态函式库与静态函式库,动态函式库在升级上具有较佳的优势。动态函式库的扩展名为 *.so 而静态则是 *.a ; 可以利用 ldconfig 与 /etc/ld.so.conf  /etc/ld.so.conf.d/*.conf 来制作动态函式库的链接与快取。

参考资料文献

《鸟哥的Linux私房菜-基础篇》

0 人点赞