2018.8.9日,预习笔记,Linux软件包安装和卸载

  1. 安装软件包的三种方法
  2. rpm包介绍
  3. rpm工具用法
  4. yum工具用法
  5. yum搭建本地仓库
  6. yum更好本地源
  7. yum下载rpm包
  8. 源码包安装
  9. yum保留已经安装过的包 
  10. 搭建局域网yum源
  11. 把源码包打包成rpm包

一.安装软件包的三种方法

  • 安装软件包的三种方法
  • rpm工具,红帽子公司包管理系统
  • yum工具,安装的时候会把需要依赖的包给安装上,比较方便
  • 源码包,可以通过编译器,把他编译成可执行的文件

二.rpm包介绍

  • 进行下图操作,ls查看d82933210038768771e0687dd3962071818.jpg
  • 获得下图内容,这其实就是rpm包

2018.8.9日,预习笔记,Linux软件包安装和卸载_第1张图片

  • rpm包格式

36b72a3ca060127b4538e12a4406fe50f1f.jpg

三.rpm工具用法

  • 2018.8.9日,预习笔记,Linux软件包安装和卸载_第2张图片
  • rpm安装

2b3f243d39da01662a21cbfa446378510f7.jpg

  • 升级rpm包

5b6704705a0a9bb97a3abbd69d5a0a651fd.jpg

  • 卸载rpm包

652e777386d772559a47ebe247144b754b2.jpg

  • 查询安装的包

0b29da58811c0524f2dc67fd16f7a2f42c4.jpg

  • 查询指定包是否安装

9d3bf29101ba543eeeb29eae5e478d74253.jpg

  • 查看指定包的信息

2018.8.9日,预习笔记,Linux软件包安装和卸载_第3张图片

  • 列出包安装的文件

2018.8.9日,预习笔记,Linux软件包安装和卸载_第4张图片

  • 知道命令的路径,查看一个命令是由谁安装的

28b460f03266e6ed055fcdf23fd50ea966c.jpg

  • 不知道命令的路径,查看一个命令是由谁安装的

a6e6aa6f4f8a869421b4c87b028266826c3.jpg

 

四.yum工具用法

2018.8.9日,预习笔记,Linux软件包安装和卸载_第5张图片

  • 查看yum的核心配置文件

2018.8.9日,预习笔记,Linux软件包安装和卸载_第6张图片

  • 是用yum搜索安装包,不过不够精细

2018.8.9日,预习笔记,Linux软件包安装和卸载_第7张图片

  • 精细一点的查找命令安装包,使用过滤

2018.8.9日,预习笔记,Linux软件包安装和卸载_第8张图片

  • #yum install [-y]安装一个包,加-y,不提示直接安装
  • #yum grouplist把可用的组全部列出来

2018.8.9日,预习笔记,Linux软件包安装和卸载_第9张图片

  • 安装可用环境分组

2018.8.9日,预习笔记,Linux软件包安装和卸载_第10张图片

  • 卸载包的时候同时把依赖的包也给卸载掉

2018.8.9日,预习笔记,Linux软件包安装和卸载_第11张图片

  • #yum update [-y] 升级rpm包
  • #yum provides "/*/vim"搜索rpm安装包

2018.8.9日,预习笔记,Linux软件包安装和卸载_第12张图片

 

五.yum搭建本地仓库

2018.8.9日,预习笔记,Linux软件包安装和卸载_第13张图片

  • 实验一,建立一个本地仓库
  • 挂载光驱到/mnt下
  • 做下图操作,拷贝文件,删除文件

2018.8.9日,预习笔记,Linux软件包安装和卸载_第14张图片

  • 编辑该文件,输入下图内容

2018.8.9日,预习笔记,Linux软件包安装和卸载_第15张图片

  • 做如下操作,清除一下缓存

2018.8.9日,预习笔记,Linux软件包安装和卸载_第16张图片

  • 用#yum list 查看一下rpm包

4de4143a35e640271588e171733d77b1592.jpg

2018.8.9日,预习笔记,Linux软件包安装和卸载_第17张图片

  • 用#yum list |lass 查看一下,一屏一屏看

六.yum更换国内源

2018.8.9日,预习笔记,Linux软件包安装和卸载_第18张图片

七.yum下载rpm包

实验一:安装扩展源

2018.8.9日,预习笔记,Linux软件包安装和卸载_第19张图片

  • 安装release

38a2b5b5370637079f5f9a6dc31e1665443.jpg

  • #cat一下下图文件

2018.8.9日,预习笔记,Linux软件包安装和卸载_第20张图片

  • #yum list 查看一下有哪些rpm包

6e7ea83c811883cb85d123e6012d11e8a8c.jpg

  • #yum list |grep epel 操作,查看一下

2e8f1087f6ff63fb2d9654bc2ee0ba6a73b.jpg

 

实验二: yum下载rpm包

2018.8.9日,预习笔记,Linux软件包安装和卸载_第21张图片

  • 仅仅下载,不安装

e649141fbf4e7b30b1443051965d1a9f2e1.jpg

  • 会被下载到下图路径下

2018.8.9日,预习笔记,Linux软件包安装和卸载_第22张图片

  • 下图目录里会放我们的rpm包

1f7b58fb7cadbe78d52b2247639426c626a.jpg

  • 指定下载的目录

910d2d09c392f79baae79a1f91a8003c6d0.jpg

 

八.源码包安装

2018.8.9日,预习笔记,Linux软件包安装和卸载_第23张图片

实验一:源码包安装

  • 源码包存放在 /usr/local/src路径下

40a03121b4af19f7778d4e6812385743441.jpg

  • 下载源码包

2018.8.9日,预习笔记,Linux软件包安装和卸载_第24张图片

  • ls 一下

024c22fa3cafce4e65e7cec609c68122e77.jpg

  • 解压该文件

5188a3d7537cc48510b67c4453b6c0d025b.jpg

  • #cd 进入该目录下

2018.8.9日,预习笔记,Linux软件包安装和卸载_第25张图片

  • #more下README ,这是个说明介绍文档

2018.8.9日,预习笔记,Linux软件包安装和卸载_第26张图片

  • #more 下INSTALL 这个是安装文档,介绍怎么安装

cb48a3cdee354e3c5b95f4d3cd83aaec203.jpg

  • 指定它的安装路径

d851c18945f1762338fdd08a8b61e014a58.jpg

  • echo ¥? 查看上一条命令运行是否正常,0则是没有错误

ada4d5f304b6f07a7cb70d43a2383cb7adf.jpg

  • meke一下

2018.8.9日,预习笔记,Linux软件包安装和卸载_第27张图片

  • 把编译完成的文件放到指定的目录下

2018.8.9日,预习笔记,Linux软件包安装和卸载_第28张图片

  • #ls 查看一下

d81a9e3cd6a86c3b12b74a7a8c48fb14948.jpg

  • 卸载的话,直接删除目录文件就行了

九.yum保留已经安装过的包

实验一:

  • 可以设置yum保留意见下载的rpm包,工以后升级或者重新安装时使用。
  • 修改/etc/yum.conf即可:

[main]

cachedir=/home/soft1/yumcache

keepcache=1

debuglevel=2

chchedir是放置下载的包的地方,可以修改为自己想要放置的位置。keepcache为1是表示保存意见下载的rpm包。

 

 

十.搭建局域网yum源

实验一:

  • 实验目的:

学习安装vsftpd软件,了解yum源仓库搭建过程,搭建第三方的yum源仓库。

  • 实验环境:

VMware Workstation 12.0.0 build-2985596 CentOS-7-x86_64-Everything-1611.iso

  • 开始:
  • 1.实验前要求,确保虚拟机的安装的CentOS7是以桥接的方式联入局域网,能获取局域网IP,这样其他局域网内机器就可访问此CentOS系统。
  • 2.准备网络服务,这里我们使用ftp服务(rpm安装vsftpd包)。

[root@centos7 ~]# rpm -q vsftpd # 查看是否按安装vsftpd包 package vsftpd is not installed

[root@centos7 ~]# mkdir /mnt/cdrom # 创建光盘挂载点

[root@centos7 ~]# mount /dev/sr0 /mnt/cdrom # 虚拟机载入光盘,挂载光盘到/mnt/cdrom mount: /dev/sr0 is write-protected, mounting read-only

[root@centos7 ~]# rpm -ivh /mnt/cdrom/Packages/vsftpd-3.0.2-21.el7.x86_64.rpm # rpm方式安装vsftp服务 Preparing... ################################# [100%] Updating / installing... 1:vsftpd-3.0.2-21.el7 ################################# [100%]

  • 3.启动vsftpd服务,设为下次开机启动。
[root@centos7 ~]# systemctl start vsftpd  # 手动启动vsftp服务
[root@centos7 ~]# netstat -ntl | grep 21  # 查看21端口,有说明vsftp已启动
tcp6       0      0 :::21                   :::*                    LISTEN 
[root@centos7 ~]# systemctl enable vsftpd  # 将vsftp服务设为下次开机启动
Created symlink from /etc/systemd/system/multi-user.target.wants/vsftpd.service to /usr/lib/systemd/system/vsftpd.service.
[root@centos7 ~]# systemctl is-enabled vsftpd # 查看vsftp服务设为下次开机启动是否成功
enabled  # enable表示下次开机启动,disable表示下次开机时不启动
  • 4.用命令ifconfig查看本虚拟机在局域网中的ip地址,在物理机或其他局域网中机器上用浏览器访问fftp://172.17.252.110(这是我的CentOS7的局域网地址),发现连接超时,这是因为我的CentOS7防火墙开启的缘故, 
    在实际生产环境中是修改防火墙策略,使ftp通过,这里能力有限,就把防火墙关闭了,并设为下次禁止开机启动。
[root@centos7 ~]# systemctl stop firewalld.service  # 关闭防火墙,生产环境不建议关闭防火墙
[root@centos7 ~]# systemctl disable firewalld.service  # 禁止防火墙下次开机启动
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
Removed symlink /etc/systemd/system/basic.target.wants/firewalld.service.
  • 5.在物理机或其他局域网中机器上用浏览器访问ftp://172.17.252.110 ,会出现以下页面,说明ftp服务配置成功。 

  • 6.将CentOS7安装光盘的内容复制到ftp的文件夹中/var/ftp/pub下

[root@centos7 pub]# mkdir /var/ftp/pub/centos7 # 创建文件夹
[root@centos7 pub]# cp -rvf /mnt/cdrom/* /var/ftp/pub/centos7 # 复制文件
  • 7.在物理机或其他局域网中机器上用浏览器访问ftp://172.17.252.110 ,可以看见yum源仓库已经搭建好了,局域网中其他机器可以使用此仓库作为yum源 

备注:

  • 1.上面第6步中,复制光盘文件到ftp的文件夹,其实只用复制两个目录即可,Packages(rpm包存放文件夹),repodata(存放yum仓库元数据,repodata所在的父目录为yum源的路径),如果还需要RPM数字证书,可以把RPM-GPG-KEY-CentOS-7文件复制到ftp目录。
  • 2.若是在CentOS6上搭建CentOSyum源仓库,以下地方有命令有些不同:

         a, 上面第3步应为

[root@centos6 ~]# service  vsftpd start  # 启动vsftpd服务
Starting vsftpd for vsftpd:                                [  OK  ]
[root@centos6 ~]# netstat -ntl | grep 21 # 查看服务是否开启
tcp        0      0 0.0.0.0:21                  0.0.0.0:*                   LISTEN      
[root@centos6 ~]# chkconfig vsftpd on # 将vsftpd服务设置为下次开机启动

         b, 上面第4步应为

[root@centos6 ~]# service iptables stop # 关闭防火墙
iptables: Setting chains to policy ACCEPT: filter    [  OK  ]
iptables: Flushing firewall rules:                   [  OK  ]
iptables: Unloading modules:                         [  OK  ]
[root@centos6 ~]# chkconfig iptables off # 禁止防火墙下次开机启动
  • 3 .若自己制作的rpm包或者第三方rpm,我们可以使用createrepo工具生成rpm源数据实现第三方yum源仓库。
[root@centos7 ~]# rpm -qa | grep  createrepo   # 查询是否安装createrepo工具
createrepo-0.9.9-26.el7.noarch
[root@centos7 ~]# mkdir /var/ftp/pub/app       # 创建放置第三方rpm的目录
[root@centos7 ~]# cp /mnt/cdrom/Packages/tree-1.6.0-10.el7.x86_64.rpm  /var/ftp/pub/app  #  假定tree-1.6.0-10.el7.x86_64.rpm是第三方制作的rpm
[root@centos7 ~]# ls -l /var/ftp/pub/app
total 48
-rw-r--r--. 1 root root 47508 Jun 13 16:43 tree-1.6.0-10.el7.x86_64.rpm
[root@centos7 ~]# createrepo /var/ftp/pub/app # 为第三方rpm生成yum源仓库的rpm元数据
Spawning worker 0 with 1 pkgs
Workers Finished
Saving Primary metadata
Saving file lists metadata
Saving other metadata
Generating sqlite DBs
Sqlite DBs complete

 

十一.把源码包打包成rpm包

RPM 包制作

RPM Package Manager 简称 RPM,这一文件格式在历史名称上虽然打着 RedHat 标志,但其原始设计理念是开放式的,现在包括 OpenLinux、SuSE、Turbo Linux 等多个 Linux 分发版本都有采用,可以算是公认的行业标准了。

在此介绍下如何制作 RPM 包,尤其是如何写 .spec 配置文件,以及常见的技巧。

简介

若要构建一个标准的 RPM 包,需要创建 .spec 文件,其中包含软件打包的全部信息。然后,使用 rpmbuild 命令,按照 spec 文件的配置,系统会按照步骤生成最终的 RPM 包。

另外,需要注意的是,在使用时,需要使用普通用户,一定不要用 root 用户。

结下来,看看如何编译制作 RPM 包。

环境配置

接下来,看看如何配置一步步制作 RPM 包。

安装工具

首先,在 CentOS 中配置环境。

----- 安装环境,需要rpm-build工具来打包,该包只依赖于gdb以及rpm版本
# yum install rpm-build -y

----- 新建所需目录
$ mkdir -pv ~/rpm-maker/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}

配置环境

打包相关的配置保存在宏文件 (macrofiles) 中,默认使用 $HOME/rpmbuild 目录,用户配置文件保存在 $HOME/.rpmmacros;而制作包时的操作实际都在 topdir 指定的目录下,可以通过如下方式查看。

--- 查看所有的配置文件顺序
$ rpmbuild --showrc | grep macros

--- 确认上述的根工作目录,两种方式相同
$ rpmbuild --showrc | grep ': _topdir'
$ rpm --eval '%_topdir'

--- 设置topdir变量,然后再次验证下,确认已经修改为目标目录
$ echo "%_topdir %{getenv:HOME}/rpm-maker" > ~/.rpmmacros
$ rpm --eval '%_topdir'
--- 也可以在制作rpm包时通过--define指定
$ rpmbuild --define '_topdir rpm-maker' -ba package.spec

下载 MySQL 的源码,并保存在 SPECS 目录下,整体目录结构如下。

$ tree ~/rpm-maker
.
|-- BUILD                      ← 解压后的tar.gz包
|-- BUILDROOT                  ← 临时安装目录,会打包该目录下文件
|-- RPMS                       ← 编译后的RPM包
|-- SOURCES                    ← 所需的文件
|   `-- mysql-xxx.tar.gz       ← 包括了源码包
|-- SPECS                      ← *.spec编译脚本
|   |-- mysql-xxx.spec
|   `-- mysql-yyy.spec
`-- SRPMS                      ← src格式的rpm包存放的位置

执行命令

接下来,看看如何生成 rpm 包,也就是使用 rpmbuild 命令,过程可以分为多个阶段。

$ rpmbuild --bb mysql.spec   

使用参数:
   -bb 制作成二进制RPM包
   -bs 制作源码的RPM包
   -ba 源码和二进制两种形式的RPM包
   -bl 检测BUILDROOT没有包含到rpm包中的文件

   -bp 执行到pre
   -bc 执行到build段
   -bi 执行install段

   --quiet 默认会输出每次执行的shell命令,此时忽略

----- 通过源码包重新编译
$ rpmbuild --rebuild package-0.0-0.src.rpm

----- 编译时指定参数
$ rpmbuild -bb SPECS/librdkafka.spec --define "__version 0.9.4" --define "__release 1"

一般来说,执行的顺序为 rpmbuild -bp,再 -bc 再 -bi,如果没问题,rpmbuild -ba 生成 src 包与二进制包,使用时通过 rpm -ivh xxx.rpm; 以及 rpm -e xxx.rpm 进行安装卸载。

执行步骤

1. 在 %prep 段中,通过 %setup -q 宏解压、打补丁,一般是从 SOURCES 目录下解压到 BUILD 目录下,一般目录是 "NAME-VERSION" 。
2. 通过 %build 段定义了如何进行编译,编译目录就是上述的 BUILD/NAME-VERSION 。
   2.1 首先通过 %configure %cmake 进行配置。
   2.2 然后利用 %{__make} %{?_smp_mflags} 进行并行编译。
3. 接着就是安装,也就是 %install 字段,一般会在 BUILDROOT/NAME-VERSION-RELEASE-ARCH 目录下。
   3.1 通常为了清理环境会先使用 rm -rf %{buildroot} 清理。
   3.2 接着通过 %{__make} install DESTDIR=%{buildroot} 命令进行安装,其中 DESTDIR 相当于是根目录了。
   3.3 通过上步安装的文件,需要都打包到 RPM 包中,如果不需要那么就先清理掉。
   3.4 编译没有生成的也可以通过 %{__install} %{__mv} %{__rm} 命令直接复制。
4. 执行检查规范,对应了 %test 段,一般执行一些单元测试。
5. 开始打包
6. 在 %clean 段处理清理操作,通常会通过 rm -rf %{buildroot} 删除编译的中间内容。

另外,还有 %check 字段,用于做些检查。

SPEC 文件

接下来准备 spec 文件,也是核心的内容,该文件包括三部分:介绍部分,编译部分,files 部分。接下来,是一个简单的示例,可以看看到底是如何制作 RPM 包的。

### 0.define section                ← ###自定义宏段(可选),方便后续引用
%define mysql_user mysql                            ← 定义宏,方便后续引用
%define _topdir /home/jinyang/databases/rpm-maker

### 1.The introduction section      ← ###介绍区域段
Name:           mysql                               ← 包名称,通常会在指定源码压缩包时引用
Version:        5.7.17                              ← 版本号,同上
Release:        1%{?dist}                           ← 释出号,每次制作rpm包时递增该数字
Summary:        MySQL from FooBar.                  ← 软件包简介,最好不要超过50字符
License:        GPLv2+ and BSD                      ← 许可,GPL、BSD、MIT等,也可以使用or

Group:          Applications/Databases              ← 程序组名,从/usr/share/doc/rpm-VER/GROUPS选择
URL:            http://kidding.com                  ← 一般为官网
Source0:        %{name}-boost-%{version}.tar.gz     ← 源码包名称(可以使用URL),可以用SourceN指定多个,如配置文件
#Patch0:         some-bugs.patch                    ← 如果需要打补丁,则依次填写
BuildRequires:  gcc,make                            ← 制作过程中用到的软件包
Requires:       pcre,pcre-devel,openssl,chkconfig   ← 安装时所需软件包,可使用bash >= 1.1.1
Requires(pre):  test                                ← 指定不同阶段的依赖

BuildRoot:      %_topdir/BUILDROOT                  ← 会打包该目录下文件,可查看安装后文件路径
Packager:       FooBar 
Vendor:         kidding.com

%description                        ← ###软件包的详细描述,可以撒丫子写了
It is a MySQL from FooBar.

#--- 2.The Prep section             ← ###准备阶段,主要是解压源码,并切换到源码目录下
%prep
%setup -q                                           ← 宏的作用是解压并切换到目录
#%patch0 -p1                                        ← 如果需要打补丁,则依次写

#--- 3.The Build Section            ← ###编译制作阶段,主要目的就是编译
%build

make %{?_smp_mflags}                                ← 多核则并行编译

#--- 4.Install section              ← ###安装阶段
%install
if [-d %{buildroot}]; then
   rm -rf %{buildroot}                              ← 清空下安装目录,实际会自动清除
fi
make install DESTDIR=%{buildroot}                   ← 安装到buildroot目录下
%{__install} -Dp -m0755 contrib/init.d %{buildroot}%{_initrddir}/foobar
%{__install} -d %{buildroot}%{_sysconfdir}/foobar.d/

#--- 4.1 scripts section            ← ###没必要可以不填
%pre                                                ← 安装前执行的脚本
%post                                               ← 安装后执行的脚本
%preun                                              ← 卸载前执行的脚本
%postun                                             ← 卸载后执行的脚本
%pretrans                                           ← 在事务开始时执行脚本
%posttrans                                          ← 在事务结束时执行脚本

#--- 5. Clean section               ← ###清理段,可以通过--clean删除BUILD
%clean
rm -rf %{buildroot}

#--- 6. File section                ← ###打包时要包含的文件,注意同时需要在%install中安装
%files
%defattr (-,root,root,0755)                         ← 设定默认权限
%config(noreplace) /etc/my.cnf                      ← 表明是配置文件,noplace表示替换文件
%doc %{src_dir}/Docs/ChangeLog                      ← 表明这个是文档
%attr(644, root, root) %{_mandir}/man8/mysqld.8*    ← 分别是权限,属主,属组
%attr(755, root, root) %{_sbindir}/mysqld

#--- 7. Chagelog section            ← ###记录SPEC的修改日志段
%changelog
* Fri Dec 29 2012 foobar  - 1.0.0-1
- Initial version

对于 %config(noreplace) 表示为配置文件,且不能覆盖,新安装时如果配置文件存在则会将原文件保存为 *.rpmsave ,升级时则不会覆盖原文件,直接将包中的文件命名为 *.rpmnew,更详细内容可以参考 RPM, %config, and (noreplace) 。

关于脚本部分,通常所有安装脚本和触发器脚本都是使用 /bin/sh 来执行的,如果想使用其他脚本,如 Lua,可使用 -p /usr/bin/lua 来告诉 rpm 使用 lua 解释器。如

%post -p /usr/bin/lua
# lua script here
%postun -p /usr/bin/perl
$ perl sciprt here

另外,如果只执行一条命令,也使用 -p 选项可直接执行,如 %post -p /sbin/ldconfig 。

一般最后一条命令的 exit 状态就是脚本的 exit 状态,除一些特殊情况,一般脚本都是以 exit 0 状态退出,所以大部分小脚本片段都会使用 "||:" 退出。

%prep

%setup -q -T -a 0 -a 7 -a 10 -c -n %{src_dir}
参数列表:
    -T 禁止自动解压源码文件
    -D 解压前不删除目录
    -a 切换目录前,解压指定Source文件,例如-a 0表示解压Source0
    -b 切换目录后,解压指定Source文件,例如-a 0表示解压Source0
    -n 解压后目录名称与RPM名称不同,则通过该参数指定切换目录
    -c 解压缩之前先生成目录

systemd

spec 脚本中提供了与 systemd 相关的脚本,关于脚本的详细内容可以查看 macros.systemd.in,实用方式很简单,如下:

----- 安装结束后,实际执行systemctl preset,执行服务预设的内容
%systemd_post foobar.service

----- 执行卸载前,systemctl disable
%systemd_preun foobar.service

----- 卸载后执行重启操作,daemon-reload+try-restart
%systemd_postun_with_restart foobar.service

----- 如果不需要重启,例如有状态链接的(D-Bus),执行systemctl daemon-reload
%systemd_postun foobar.service

关于安装升级的各个操作步骤详见 RPM SPEC pre/post/preun/postun argument values 以及 Fedora Packaging Guidelines for RPM Scriptlets 。

校验

在安装完 RPM 包之后,可以通过 --verify 或者 -V 进行校验,正常不会显示任何信息,可以通过 --verbose或者 -v 显示每个文件的信息;文件丢失显示 missing,属性方面的修改内容如下:

SM5DLUGT c filename
属性:
  S: 文件大小;
  M: 权限;
  5: MD5检查和;
  D: 主从设备号;
  L: 符号连接;
  U: 属主;
  G: 属组;
  T: 最后修改时间。
类型:
  c: 配置文件;
  d: 文档文件。

增加签名

当制作 RPM 包之后,为了防止被篡改,可以使用私钥进行签名,然后将公钥开放出去,然后用户下载完软件包可以通过公钥进行验证签名,从而确保文件的原始性。

可以通过如下步骤进行操作。

1. 生成密钥对

首先,需要使用 gpp 来生成公私钥对,一般可以使用 RSA 非对称加密。

$ gpg --gen-key

此时会在 ~/.gnupg 目录下创建相关文件,创建完后可以通过如下命令查看当前的密钥对。

$ gpg --list-keys
/home/foobar/.gnupg/pubring.gpg
------------------------------
pub   2048R/860FB269 2017-01-13
uid                  foobar (just for test) 

其中 UID 分别对应了用户名、注释、邮箱。

2. 软件包签名

修改 RPM 宏,使用上述生成的密钥对。

$ echo %_signature gpg >> ~/.rpmmacros
$ echo "%_gpg_name foobar (just for test)" >> ~/.rpmmacros

对已有 rpm 软件包进行签名。

$ rpm --addsign package_name.rpm
Enter pass phrase:
Pass phrase is good.
package_name.rpm

如果失败,则会出现如下的错误。

$ rpm --addsign package_name.rpm
Enter pass phrase:
Pass phrase check failed.

此时需要仔细检查密钥名称和写入 rpm 宏里面的是否一致,最好是将 --list-keys 显示的内容整体复制出来。

当然也可以在通过 rpmbuild --sign 打包时自动包含签名。

3. 增加签名

生成签名使用的是私钥,验证签名需要使用公钥。简单来说需要执行:1)将 gpg 产生的公钥导出到一个文件;2) 将这个公钥文件导入到 RPM 数据库里;3) 使用 rpm 命令进行检验。

----- 导出公钥到一个文本文档
$ gpg --export -a "foobar (just for test)" > RPM-GPG-KEY-FOOBAR

----- 查看rpm数据库中已有的公钥
$ rpm -q gpg-pubkey-*
gpg-pubkey-f4a80eb5-53a7ff4b
gpg-pubkey-352c64e5-52ae6884
gpg-pubkey-442df0f8-4783f24a

----- 将公钥导入到RPM数据库,注意需要root用户执行
# rpm --import RPM-GPG-KEY-FOOBAR

通过上述命令重新查看公钥时,会发现新增了一个 gpg-pubkey-860fb269-5a65a0ad 公钥,其中 860FB269 与上述 gpg 生成的密钥信息相同。

如果不需要,可以通过 rpm -e gpg-pubkey-860fb269-5a65a0ad 删除即可。

4. 签名验证

通过 rpm -K package_name.rpm 命令对签名验证即可,如下是验证成功以及失败时输出的内容。

package_name.rpm: rsa sha1 (md5) pgp md5 OK
package_name.rpm: RSA sha1 (MD5) (PGP) (MD5) (PGP) md5 NOT OK (MISSING KEYS: PGP#c0eb63c7 PGP#c0eb63c7)

其它

如果导入公钥失败,那么在安装时会生成一个类似 Header V3 RSA/SHA1 signature: NOKEY, key ID c0eb63c7 的告警信息。

如果要在 YUM 中验证签名,可以将公钥复制到系统 RPM 公钥目录,一般如下操作即可。

# cp RPM-GPG-KEY-FOOBAR /etc/pki/rpm-gpg/

在源配置文件中通过如下两行来指定 gpg key 检验:

gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-FOOBAR

这样在通过 YUM 安装软件包时,当下载完毕以后会首先使用公钥进行签名验证。

常用设置

接下来,看看一些常用的实用技巧。

在一个 SPEC 文件中可以同时打包多个 RPM 包,当然也可以通过 %package -n foobar 指定子模块 (subpackage) 的名称 。

宏定义

在定义文件的安装路径时,通常会使用类似 %_sharedstatedir 的宏,这些宏一般会在 /usr/lib/rpm/macros 中定义,当然部分会同时在不同平台上覆盖配置,可以直接 grep 查看。

RPM 内建宏定义在 /usr/lib/rpm/redhat/macros 文件中,这些宏基本上定义了目录路径或体系结构等等;同时也包含了一组用于调试 spec 文件的宏,关于 Macro 详细可以查看 Macro syntax,其中常用如下:

%dump                 打印宏的值,包括一些内建的宏定义,也可以通过rpm --showrc查看
%{echo:message}       打印信息到标准输出
%{warn:message}       打印信息到标准错误
%{error:message}      打印信息到标准错误,然后返回BADSPEC
%{expand:expression}  类似Bash中的eval内置命令

另外常用的是根据宏来设置变量。

%{?foobar:expr} 如果宏 foobar 存在则使用 expand expr,否则为空;也可以取反 %{!?foobar:expr}
%{?macro}       只测试该宏是否存在,存在就用该宏的值,反之则不用,如 %configure %{?_with_foobar}

另外,在判断宏的 Bool 值时,可以通过如下方式测试,如果 variable 定义,则为 01 也就是 true 否则为 0

%if 0%{?variable:1}
... ...
%endif

配置脚本

很多制作 RPM 包的操作都是通过宏定义设置的,如下简单列举一下常见的宏定义操作。

__os_install_post
    安装完之后的操作,例如去除二进制文件中的注释等;
__spec_install_pre
    在安装前的操作,设置一些环境变量,然后删除BUILDROOT中的文件(如果文件多时耗时增加);

如果想取消某些操作,可以将这些操作设置为 %{nil} 即可。

----- 查看对应的命令
$ rpm --showrc | grep -A 4 ': __os_install_post'
-14: __os_install_post
    /usr/lib/rpm/redhat/brp-compress
    %{!?__debug_package:
    /usr/lib/rpm/redhat/brp-strip %{__strip}
    /usr/lib/rpm/redhat/brp-strip-comment-note %{__strip} %{__objdump}

----- 在SPEC文件头部添加如下内容
%global __os_install_post %{nil}

----- 在用户的~/.rpmmacros文件中添加如下配置
%__os_install_post %{nil}

define vs. global

两者都可以用来进行变量定义,不过在细节上有些许差别,简单列举如下:

  • define 用来定义宏,global 用来定义变量;
  • 如果定义带参数的宏 (类似于函数),必须要使用 define;
  • 在 %{} 内部,必须要使用 global 而非 define;
  • define 在使用时计算其值,而 global 则在定义时就计算其值;

可以简单参考如下的示例。

#--- %prep之前的参数是必须要有的
Name:           mysql
Version:        5.7.17
Release:        1%{?dist}
Summary:        MySQL from FooBar.
License:        GPLv2+ and BSD

%description
It is a MySQL from FooBar.

%prep
#--- 带参数时,必须使用%define定义
%define myecho() echo %1 %2
%{!?bar: %define bar defined}

echo 1: %{bar}
%{myecho 2: %{bar}}
echo 3: %{bar}

# 如下是输出内容
#1: defined
#2: defined
#3: %{bar}

显然 3 的输出是不符合预期的,可以将 %define 修改为 global 即可。

变量使用

define 定义的变量类似于局部变量,只在 %{!?foo: ... } 区间有效,不过 SPEC 并不会自动清除该变量,只有再次遇到 %{} 时才会清除,WTF!!!

在命令行中通过 --define 'with_ssl bundled' 进行定义,在 SPEC 脚本中,使用 %{?with_ssl: } 处理上述参数,或者通过 %{!?with_ssl: } 处理未定义参数时的情况。

#--- 根据传入的变量,设置好相应的ssl_option变量
%{?with_ssl: %global ssl_option -DWITH_SSL=%{with_ssl}}

#--- 接下来,通过如下方式使用上述定义的变量
%{?ssl_option}

在 RPM 中,问号 ? 用于条件检测,默认如果对应的变量值不存在,那么 RPM 会原样保留字符串,通过问号表示,如果不存在则移除。

$ rpm --eval='foo:%{foo}'$'\n''bar:%{?bar}'
foo:%{foo}
bar:

$ rpm --define='foo foov' --eval='foo:%{foo}'$'\n''bar:%{?bar}'
foo:foov
bar:

$ rpm --define='foo foov' --define='bar barv' --eval='foo:%{foo}'$'\n''bar:%{?bar}'
foo:foov
bar:barv

除了上述的表示方法外,还可以使用如下内容:

%define _without_foobar            1
# enabled by default
%define with_foobar 0%{!?_without_foobar:1}

如果 _without_foobar 变量不存在,那么默认 with_foobar 为 01 也就是 true,否则就是 0 也就是 false;可以通过如下命令行进行测试。

$ rpm --define='with_foobar 0%{!?_without_foobar:1}' --eval='foobar:%{with_foobar}'
foobar:01
$ rpm --define='_without_foobar 1' --define='with_foobar 0%{!?_without_foobar:1}' --eval='foobar:%{with_foobar}'
foobar:0

其它

如下是 %if 判断的使用。

%if 0%{?rhel} == 6
%global compatver             5.1.17
BuildRequires:  systemd
%else
%global compatver             5.1.17
BuildRequires:  sysv
%endif

可以使用 Requires(pre)、Requires(post) 等都是针对不同阶段的依赖设置;可以通过 %package PACKAGE-NAME设置生成不同的 RPM 分支包。

另外,可以生成 GPG 签名,在此不再赘述。

添加用户

可以在 %pre 段中添加如下内容。

/usr/sbin/groupadd -g 66 -o -r monitor >/dev/null 2>&1 || :

参数:
  --gid/-g
    指定group id;
  --non-unique/-o
    group id可以不唯一,此时相当于指定了一个 alias;
  --system/-r
    创建系统分组;

/usr/sbin/useradd -M %{!?el5:-N} -g monitor -o -r -d %{_libdir}/%{name} -s /bin/false \
    -c "Uagent Server" -u 66 monitor >/dev/null 2>&1 || :
参数:
  --no-create-home/-M
    不创建HOME目录;
  --no-user-group/-N
    不创建相同用户名的分组;
  --non-unique/-o
    user id可以不唯一,此时相当于指定了一个 alias;
  --system/-r
    创建系统用户;
  --home-dir/-d HOME_DIR
    指定HOME目录,如果不存在则会创建;
  --shell/-s SHELL
    指定默认的shell;

初始宏定义

很多的宏,是在 /etc/rpm 目录下定义的,如上面的 dist 在 /etc/rpm/macros.dist 文件中定义。

RPM包查看

对于生成的 RPM 包,只能查看头部信息和脚本内容,指令分别如下。

$ rpm --info -qp XXX.rpm
$ rpm --scripts -qp XXX.rpm

变量定义

在定义 Version 时,如果使用 %{?package_version:1.0.0} 可以工作但是,使用 %{!?package_version:1.0.0} 却无效。

而且这里的参数不能通过类似 rpmbuld --define='package_version 1.9.1' foobar.spec 的方式传入。

测试脚本

如下是一个测试用的脚本,可以用来生成简单的测试 SPEC 脚本,并执行。

该脚本会将 /tmp/foobar 目录作为工作目录,然后生成一个简单的 Hello world 程序,也可以直接下载 package-rpm.sh 脚本文件。

#!/bin/bash

WORKSPACE=/tmp/foobar

echo "0. Prepare dirs"
mkdir -pv ${WORKSPACE}/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS,Workspace/foobar-1.0.0}

echo "1. Generate tar"
cd ${WORKSPACE}/Workspace/foobar-1.0.0
cat << EOF > main.c
#include 

int main(int argc, char *argv)
{
    printf("Hello World!!!\n");
        return 0;
}
EOF
cat << "EOF" > Makefile
all: main.c
	gcc -o foobar $< -Wall
install:
	install -m 755 foobar ${DESTDIR}/usr/bin/foobar
EOF
cd ${WORKSPACE}/Workspace
tar -jcf foobar-1.0.0.tar.bz2 foobar-1.0.0
#[ "${WORKSPACE}/BUILD" != "/" ] && rm -rf "${WORKSPACE}/BUILD/"
rm -rf "${WORKSPACE}/SOURCES/foobar-1.0.0.tar.bz2"
mv foobar-1.0.0.tar.bz2 ${WORKSPACE}/SOURCES/

echo "2. Prepare spec-file"
cd ${WORKSPACE}
cat << EOF > SPECS/foobar-1.0.0.spec
### 0. The define section
%global _topdir ${WORKSPACE}

### 1.The introduction section
Name:           foobar
Version:        1.0.0
Release:        1%{?dist}
Summary:        Just a RPM example
License:        GPLv2+ and BSD
BuildRequires:  gcc,make
Source0:        %{name}-%{version}.tar.bz2
BuildRoot:      %_topdir/BUILDROOT

%description
It is a RPM example.

#--- 2.The Prep section
%prep
%setup -q
#%patch0 -p1

#--- 3.The Build Section
%build
make %{?_smp_mflags}
#echo %{_sysconfdir}

%install
#/usr/bin/
install -d -m 0751 %{buildroot}/%{_bindir}
make install DESTDIR=%{buildroot}
#--- 4.1 scripts section
%pre
echo "pre" >> /tmp/foobar
%post
echo "post" >> /tmp/foobar
%preun
echo "preun" >> /tmp/foobar
%postun
echo "postun" >> /tmp/foobar

#--- 5.clean section
%clean
rm -rf %{buildroot}

#--- 6.file section
%files
%defattr(-,root,root,-)
%attr(755, root, root) %{_bindir}/foobar

#--- 7.chagelog section
%changelog
* Fri Dec 28 2012 foobar [email protected] - 1.0.0-1
- Initial version
EOF

echo "3. Perform rpmbuild"
cd ${WORKSPACE}
rpmbuild --clean --define '_topdir /tmp/foobar' -ba SPECS/foobar-1.0.0.spec

参考示例

如上介绍了手动如何编译生成 rpm 包,这里通过 collectd 看看,如何使用一些常见的工具,更加方便的制作 rpm 包,可以参考 collectd 创建的示例 。

# yum install rpmdevtools yum-utils

----- 配置环境,生成topdir工作目录~/rpmbuild,以及配置文件~/.rpmmacros
$ rpmdev-setuptree

----- 下载collectd源码,并解压
$ mkdir ~/src && cd ~/src && curl --progress https://collectd.org/files/collectd-5.5.3.tar.gz | tar xz

 

 

 

 

 

转载于:https://my.oschina.net/u/3912766/blog/1926070

你可能感兴趣的:(2018.8.9日,预习笔记,Linux软件包安装和卸载)