make编译安装
本节内容来源鸟哥私房菜,第二十二章、软件安装:原始码与 Tarball,有兴趣朋友建议看原版。
gcc相关知识
先编写一个C文件,其第一行表示包含文件在/usr/include/stdio.h
下,如果没有申明,则需要使用参数-I /usr/include
指定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
[root@home ~]#cat sin.c #include <stdio.h> int main(void) { float value; value=sin(3.14/2); printf("%.2f\n",value); } [root@localhost src]# gcc -c sin.c sina.c: In function ‘main’: sina.c:5:8: warning: incompatible implicit declaration of built-in function ‘sin’ [enabled by default] value=sin(3.14/2); ^ [root@7ftbv7mdz7cdpc ~]# gcc -c sin.c -lm -L /lib/64 -L /usr/lib64 sin.c: In function ‘main’: sin.c:5: warning: incompatible implicit declaration of built-in function ‘sin’ [root@localhost src]# gcc -o sin sina.o [root@localhost src]# ./sin 1.00 |
gcc sin.c
全产生a.out运行文件,加上参数-c
则生成二进制文件sin.o,再加上-o则生成运行档sin。
但是如果出现以下错误,这是因为 C 语言里面的 sin 函示是写在 libm.so 这个函式库中,而我们并没有在原始码里面将这个函式库功能加进去,可以使用以下命令gcc -c sin.c -lm -L /lib/64 -L /usr/lib64
- gcc -O 为产生最佳化的参数
- gcc -Wall 为产生更详细的编译过程资讯
- -l :是『加入某个函式库(library)』的意思,
- m :则是 libm.so 这个函式库,其中, lib 与扩展名(.a 或 .so)不需要写
- -I /path 后面接的路径( Path )就是配置要去搜寻相关的 include 文件的目录啦
- -L 后面接的路径表示函式库 libm.so 请到 /lib 或 /usr/lib 里面搜寻
总结:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
仅将原始码编译成为目标档,并不制作连结等功能: [root@www ~]# gcc -c hello.c 会自动的产生 hello.o 这个文件,但是并不会产生 binary 运行档。 在编译的时候,依据作业环境给予最佳化运行速度 [root@www ~]# gcc -O hello.c -c 会自动的产生 hello.o 这个文件,并且进行最佳化喔! 在进行 binary file 制作时,将连结的函式库与相关的路径填入 [root@www ~]# gcc sin.c -lm -L/usr/lib -I /usr/include 这个命令较常下达在最终连结成 binary file 的时候, -lm 指的是 libm.so 或 libm.a 这个函式库文件; -L 后面接的路径是刚刚上面那个函式库的搜寻目录; -I 后面接的是原始码内的 include 文件之所在目录。 将编译的结果输出成某个特定档名 [root@www ~]# gcc -o hello hello.c -o 后面接的是要输出的 binary file 档名 在编译的时候,输出较多的信息说明 [root@www ~]# gcc -o hello hello.c -Wall 加入 -Wall 之后,程序的编译会变的较为严谨一点, 所以警告信息也会显示出来! |
另外,我们通常称 -Wall 或者 -O 这些非必要的参数为旗标 (FLAGS),因为我们使用的是 C 程序语言,所以有时候也会简称这些旗标为 CFLAGS。
makefile介绍
实例
首先,下载wget http://linux.vbird.org/linux_basic/0520source/main.tgz
然后开始编译:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
[root@localhost main]# cat makefile main: main.o haha.o sin_value.o cos_value.o gcc -o main main.o haha.o sin_value.o cos_value.o -lm clean: rm -f main main.o haha.o sin_value.o cos_value.o [root@localhost main]# make cc -c -o main.o main.c cc -c -o haha.o haha.c cc -c -o sin_value.o sin_value.c cc -c -o cos_value.o cos_value.c gcc -o main main.o haha.o sin_value.o cos_value.o -lm [root@localhost main]# ./main Please input your name: fdm Please enter the degree angle (ex> 90): 33 Hi, Dear fdm, nice to meet you. The Sin is: 0.54 The Cos is: 0.84 [root@localhost main]# make clean rm -f main main.o haha.o sin_value.o cos_value.o |
makefile 的基本语法与变量
make 会主动的去判断每个目标档相关的原始码文件,并直接予以编译,最后再直接进行连结的动作。
- 在 makefile 当中的 # 代表注解;
- 需要在命令行 (例如 gcc 这个编译器命令) 的第一个字节;
- 标的 (target) 与相依文件(就是目标档)之间需以『:』隔开。就是可执行程序的文件名。
1 2
标的(target): 目标档1 目标档2 gcc -o 欲创建的运行档 目标档1 目标档2
如下,makefile 里面就具有至少两个标的,分别是 main 与 clean ,如果我们想要创建 main 的话,输入『make main』,如果想要清除有的没的,输入『make clean』即可!而如果想要先清除目标档再编译 main 这个程序的话,就可以这样输入:『make clean main』
还可以进行简化,使用变量来减少程序的修改量。$@:代表目前的标的(target);gcc 在进行编译的行为时,会主动的去读取 CFLAGS 这个环境变量,可以写到makefile
1 2 3 4 5 6 7 8 |
[root@www ~]# cat makefile LIBS = -lm OBJS = main.o haha.o sin_value.o cos_value.o CFLAGS = -Wall main: ${OBJS} gcc -o $@ ${OBJS} ${LIBS} clean: rm -f $@ ${OBJS} |
由於 gcc 在进行编译的行为时,会主动的去读取 CFLAGS 这个环境变量,所以,你可以直接在 shell 定义出这个环境变量,也可以在 makefile 文件里面去定义:
1 2 |
[root@www ~]# CFLAGS="-Wall" make clean main 这个动作在上 make 进行编译时,会去取用 CFLAGS 的变量内容! |
make与Dockerfile相接合
此小节内容来源于 high-iowait-process 。
如有下列Makefile文件内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
.PHONY: build build: gcc -o app app.c docker build -t feisky/app:iowait -f Dockerfile . gcc -o app app-fix1.c docker build -t feisky/app:iowait-fix1 -f Dockerfile . gcc -o app app-fix2.c docker build -t feisky/app:iowait-fix2 -f Dockerfile . .PHONY: push push: docker push feisky/app:iowait docker push feisky/app:iowait-fix1 docker push feisky/app:iowait-fix2 .PHONY: run run: docker run --privileged --name=app -itd feisky/app:iowait .PHONY: run-fix1 run-fix1: docker run --privileged --name=app -itd feisky/app:iowait-fix1 .PHONY: run-fix2 run-fix2: docker run --privileged --name=app -itd feisky/app:iowait-fix2 .PHONY: clean clean: rm -f app docker rm -f app || echo "Container app already deleted." |
这样写好之后,就可以使用 make bulid
来生成镜像,使用 make run
来运行镜像,使用 make clean
来删除镜像。所以这看上去就有点像脚本的函数一样了。
变量的基本语法
- 变量与变量内容以『=』隔开,同时两边可以具有空格;
- 变量左边不可以有 ,例如上面范例的第一行 LIBS 左边不可以是 ;
- 变量与变量内容在『=』两边不能具有『:』;
- 在习惯上,变量最好是以『大写字母』为主;
- 运用变量时,以 ${变量} 或 $(变量) 使用;
- 在该 shell 的环境变量是可以被套用的,例如提到的 CFLAGS 这个变量!
- 在命令列模式也可以给予变量。
yum安装相关环境
- 如果是要安装 gcc 等软件发展工具,请使用『 yum groupinstall “Development Tools” 』
- 若待安装的软件需要图形介面支持,一般还需要『 yum groupinstall “X Software Development” 』
- 若安装的软件较旧,可能需要『 yum groupinstall “Legacy Software Development” 』
编译软件步骤
- ./configure 创建Makefile文件
- make clean 会读取 Makefile 中关於 clean 的工作,可有可无
- make make 会依据 Makefile 当中的默认工作进行编译的行为
- make install
如果未指定安装路径,则编译安装的目录是放在/usr/local/etc、/usr/local/bin、/usr/local/lib、/usr/local/man下。
rpm知识
此内容与编译无关。可以跳过,同时此内容也来自于鸟哥私房菜,是一本好本啊~
RPM 安装 (install)
1 2 3 4 5 6 7 8 9 10 |
[root@www ~]# rpm -ivh package_name 选项与参数: -i :install 的意思 -v :察看更细部的安装资讯画面 -h :以安装资讯列显示安装进度 -Uvh 后面接的软件即使没有安装过,则系统将予以直接安装; 若后面接的软件有安装过旧版,则系统自动升级至新版; -Fvh 如果后面接的软件并未安装到你的 Linux 系统上,则该软件不会被安装;亦即只有已安装至你 Linux 系统内的软件会被『升级』 [root@www ~]# rpm --rebuilddb <==重建数据库 |
rpm 安装时常用的选项与参数说明
- —nodeps:当发生软件属性相依问题而无法安装,但你执意安装时
- —replacefiles:如果在安装的过程当中出现了『某个文件已经被安装在你的系统上面』的资讯,又或许出现版本不合的信息 (confilcting files) 时,可以使用这个参数来直接覆盖文件。
- —replacepkgs:重新安装某个已经安装过的软件!如果你要安装一堆 RPM 软件文件时,可以使用 rpm -ivh *.rpm ,但若某些软件已经安装过了, 此时系统会出现『某软件已安装』的资讯,导致无法继续安装。此时可使用这个选项来重复安装喔!
- —force:这个参数其实就是 —replacefiles 与 —replacepkgs 的综合体!
- —test: 想要测试一下该软件是否可以被安装到使用者的 Linux 环境当中,可找出是否有属性相依的问题。
- —justdb 使用时机: 由於 RPM 数据库破损或者是某些缘故产生错误时,可使用这个选项来升级软件在数据库内的相关资讯。
- —nosignature 使用时机: 想要略过数码签章的检查时,可以使用这个选项。
- —prefix 新路径 使用时机: 要将软件安装到其他非正规目录时。举例来说,你想要将某软件安装到 /usr/local 而非正规的 /bin, /etc 等目录, 就可以使用『 —prefix /usr/local 』来处理了。
- —noscripts 使用时机:不想让该软件在安装过程中自行运行某些系统命令。
RPM 查询 (query)
RPM 在查询的时候,其实查询的地方是在 /var/lib/rpm/
这个目录下的数据库文件。
1 2 3 4 |
[root@www ~]# rpm -qa <==已安装软件 [root@www ~]# rpm -q[licdR] 已安装的软件名称 <==已安装软件 [root@www ~]# rpm -qf 存在於系统上面的某个档名 <==已安装软件 [root@www ~]# rpm -qp[licdR] 未安装的某个文件名称 <==查阅RPM文件 |
- -q :仅查询,后面接的软件名称是否有安装;
- -qa :列出所有的,已经安装在本机 Linux 系统上面的所有软件名称;
- -qi :列出该软件的详细资讯 (information),包含开发商、版本与说明等;
- -ql :列出该软件所有的文件与目录所在完整档名 (list);
- -qc :列出该软件的所有配置档 (找出在 /etc/ 底下的档名而已)
- -qd :列出该软件的所有说明档 (找出与 man 有关的文件而已)
- -qR :列出与该软件有关的相依软件所含的文件 (Required 的意思)
- -qf :由后面接的文件名称,找出该文件属於哪一个已安装的软件
- -qp[icdlR]:注意 -qp 后面接的所有参数以上面的说明一致。但用途仅在於找出某个 RPM 文件内的资讯,即未安装的名称
RPM 验证与数码签章
验证
验证 (Verify) 的功能主要在於提供系统管理员一个有用的管理机制!作用的方式是『使用 /var/lib/rpm 底下的数据库内容来比对目前 Linux 系统的环境下的所有软件文件 』也就是说,当你有数据不小心遗失, 或者是因为你误杀了某个软件的文件,或者是不小心不知道修改到某一个软件的文件内容
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[root@www ~]# rpm -Va [root@www ~]# rpm -V 已安装的软件名称 [root@www ~]# rpm -Vp 某个 RPM 文件的档名 [root@www ~]# rpm -Vf 在系统上面的某个文件 选项与参数: -V :后面加的是软件名称,若该软件所含的文件被更动过,才会列出来; -Va :列出目前系统上面所有可能被更动过的文件; -Vp :后面加的是文件名称,列出该软件内可能被更动过的文件; -Vf :列出某个文件是否被更动过~ [root@www ~]# rpm -V logrotate ..5....T c /etc/logrotate.conf |
第一列的含义有以下几种:
1 2 3 4 5 6 7 8 |
S :(file Size differs) 文件的容量大小是否被改变 M :(Mode differs) 文件的类型或文件的属性 (rwx) 是否被改变?如是否可运行等参数已被改变 5 :(MD5 sum differs) MD5 这一种指纹码的内容已经不同 D :(Device major/minor number mis-match) 装置的主/次代码已经改变 L :(readLink(2) path mis-match) Link 路径已被改变 U :(User ownership differs) 文件的所属人已被改变 G :(Group ownership differs) 文件的所属群组已被改变 T :(mTime differs) 文件的创建时间已被改变 |
第二列的含义有以下几种:
1 2 3 4 5 |
c :配置档 (config file) d :文件数据档 (documentation) g :鬼文件~通常是该文件不被某个软件所包含,较少发生!(ghost file) l :授权文件 (license file) r :读我文件 (read me) |
数码签章
软件开发厂商可以数码签章系统产生一个专属於该软件的签章,并将该签章的公钥 (public key) 释出。 当你要安装一个 RPM 文件时:
首先你必须要先安装原厂释出的公钥文件;实际安装原厂的 RPM 软件时, rpm 命令会去读取 RPM 文件的签章资讯,与本机系统内的签章资讯比对,若签章相同则予以安装,若找不到相关的签章资讯时,则给予警告并且停止安装喔。
1 2 3 4 5 6 7 8 |
[root@localhost ~]# ll /etc/pki/rpm-gpg/RPM-GPG-KEY-* -rw-r--r--. 1 root root 1690 Nov 23 08:16 /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 -rw-r--r--. 1 root root 1004 Nov 23 08:16 /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-Debug-7 -rw-r--r--. 1 root root 1690 Nov 23 08:16 /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-Testing-7 -rw-r--r--. 1 root root 1662 Oct 2 2017 /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 -rw-r--r--. 1 root root 1340 Mar 23 2017 /etc/pki/rpm-gpg/RPM-GPG-KEY-remi -rw-r--r--. 1 root root 3100 Mar 23 2017 /etc/pki/rpm-gpg/RPM-GPG-KEY-remi2017 -rw-r--r--. 1 root root 3143 Jan 16 2018 /etc/pki/rpm-gpg/RPM-GPG-KEY-remi2018 |
SRPM相关知识
rpm的全称是Redhat Package Manager,SRPM是指 Source RPM 的意思,这个 RPM 文件里面含有原始码,特别注意的是,这个 SRPM 所提供的软件内容『并没有经过编译』。通常 SRPM 的扩展名是以 *.src.rpm 这种格式来命名的。srpm跟tarball的区别就是srpm提供了这个软件所需要的相依性软件说明、以及所有 RPM 文件所提供的数据。
rebuild直接安装
下载src.rpm包之后,可以在不修改配置的情况下,直接使用以下参数直接操作:
- —rebuild:这个选项会将后面的SRPM进行『编译』与『打包』的动作,最后会产生RPM的档案,但是产生的RPM档案并没有安装到系统上。当你使用—rebuild的时候,最后通常会发现一行字体:
Wrote: /root/rpmbuild/RPMS/x86_64/pkgname.x86_64.rpm
这个就是编译完成的RPM档案啰!这个档案就可以用来安装啦!安装的时候请加绝对路径来安装即可 - —recompile:这个动作会直接的『编译』『打包』并且『安装』啰!请注意, rebuild 仅『编译并打包』而已,而recompile 不但进行编译跟打包,还同时进行『安装』了
示例:
1 2 3 4 5 6 7 8 9 10 |
先下载软体: wget http://vault.centos.org/7.1.1503/updates/Source/SPackages/ntp-4.2.6p5-19.el7.centos.1.src.rpm 再尝试直接编译看看: rpmbuild --rebuild ntp-4.2.6p5-19.el7.centos.1.src.rpm 上面的动作会告诉我还有一堆相依软体没有安装~所以我得要安装起来才行: yum install libcap-devel openssl-devel libedit-devel pps-tools-devel autogen autogen-libopts-devel 再次尝试编译的行为: rpmbuild --rebuild ntp-4.2.6p5-19.el7.centos.1.src.rpm 最终的软体就会被放置到: /root/rpmbuild/RPMS/x86_64/ntp-4.2.6p5-19.el7.centos.1.x86_64.rpm |
SPEC编译安装
目录说明
如果你的rpm的版本<=4.4.x,那么rpmbuid工具其默认的工作路径是/usr/src/redhat
,这就使得普通用户不能制作rpm包,因为权限的问题,在制作rpm软件包时必须切换到root身份才可以。所以,rpm从4.5.x版本开始,将rpmbuid的默认工作路径移动到用户家目录下的rpmbuild目录里,即$HOME/rpmbuild
。
首先yum -y install rpm-build rpmdevtools
,然后rpmdev-setuptree
来创建工作目录,也可以不安装rpmdevtools,直接使用mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
来创建。具体的各目录的含义如下:
默认位置 | 宏代码 | 名称 | 用途 |
---|---|---|---|
~/rpmbuild/SPECS | %_specdir | Spec 文件目录 | 保存 RPM 包配置(.spec)文件 |
~/rpmbuild/SOURCES | %_sourcedir | 源代码目录 | 保存源码包(如 .tar 包)和所有 patch 补丁 |
~/rpmbuild/BUILD | %_builddir | 构建目录 | 源码包被解压至此,并在该目录的子目录完成编译 |
~/rpmbuild/BUILDROOT | %_buildrootdir | 最终安装目录 | 保存 %install 阶段安装的文件 |
~/rpmbuild/RPMS | %_rpmdir | 标准 RPM 包目录 | 生成/保存二进制 RPM 包 |
~/rpmbuild/SRPMS | %_srcrpmdir | 源代码 RPM 包目录 | 生成/保存源码 RPM 包(SRPM) |
使用rpm -ivh来安装srpm包时,会生成很多文件在/root/rpmbuild下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
[root@localhost ~]# rpm -ivh ntp-4.2.6p5-19.el7.centos.1.src.rpm Updating / installing... 1:ntp-4.2.6p5-19.el7.centos.1 ################################# [100%] [root@localhost ~]# tree /root/rpmbuild/ /root/rpmbuild/ ├── BUILD ├── BUILDROOT ├── RPMS ├── SOURCES │ ├── ntp-4.2.4p7-getprecision.patch │ ├── ntp-4.2.6p1-cmsgalign.patch 。。。 │ └── sntp.sysconfig ├── SPECS │ └── ntp.spec └── SRPMS |
解压完成之后,srpm本身就提供了spec文件,可以直接通过以下方式直接安装:
1 2 |
[root@study ~]# rpmbuild -ba ntp.spec <==编译并同时产生RPM与SRPM档案 [root@study ~]# rpmbuild -bb ntp.spec <==仅编译成RPM档案 |
spec打包流程
SPECS下是RPM包的配置文件,是RPM打包的“图纸”,这个文件会告诉rpmbuild命令如何去打包。“宏代码”这一列就可以在SPEC文件中用来代指所对应的目录,类似于编程语言中的宏或全局变量。当然~/rpmbuild这个文件夹也是有宏代码的,叫做%_topdir。
打包的过程有点像是流水线,分好几个工序:
- 首先,需要把源代码放到%_sourcedir中;
- 然后,进行编译,编译的过程是在
%_builddir(~/rpmbuild/BUILD)
中完成的,所以需要先把源代码复制到这个目录下边,一般情况下,源代码是压缩包格式,那么就解压过来即可; - 第三步,进行“安装”,这里有点类似于预先组装软件包,把软件包应该包含的内容(比如二进制文件、配置文件、man文档等)复制到
%_buildrootdir(~/rpmbuild/BUILDROOT)
中,并按照实际安装后的目录结构组装,比如二进制命令可能会放在/usr/bin下,那么就在%_buildrootdir下也按照同样的目录结构放置; - 然后,需要配置一些必要的工作,比如在实际安装前的准备啦,安装后的清理啦,以及在卸载前后要做的工作啦等等,这样也都是通过配置在SPEC文件中来告诉rpmbuild命令;
- 还有一步可选操作,那就是检查软件是否正常运行;
- 最后,生成的RPM包放置到%_rpmdir,源码包放置到%_srpmdir下。
spec文件内容
使用vim a.spec
之后,会自动生成spec的结构体,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
Name: ==>软件包的名字,后续可以用%{name}来引用 Version: ==>软件版本 Release: 1%{?dist} ==>发布的序号 Summary: ==>软件包的摘要信息 Group: ==>软件包的安装分类,参见/usr/share/doc/rpm-4.x.x/GROUPS这个文件 License: ==>GPLv2,授权方式 URL: ==>这里本来写源码包的下载路径或者自己的博客地址或者公司网址之类,无实际用处 Source0: ==>%{name}-%{version}.tar.gz源代码包的名称,这里的name和version就是前两行定义的值。如果有其他配置或脚本则依次用Source1、Source2等等往后增加即可。 BuildRequires: ==>在本机编译rpm包时需要的辅助工具,以逗号分隔。假如,要求gcc的版本至少为4.4.2,则可以写成gcc >=4.2.2。 Requires: ==>编译好的rpm软件在其他机器上安装时,需要依赖的其他软件包,也以逗号分隔,有版本需求的可以 description ==>软件包的详细说明信息,但最多只能有80个英文字符。 prep ==>读取位于 %_sourcedir 目录的源代码和 patch 。之后,解压源代码至 %_builddir 的子目录并应用所有 patch。 setup -q ==>使用这个语句实现%prep功能,仅能解压Source 或 patch 定义好的文件 build ==>编译位于 %_builddir 构建目录下的文件。通过执行类似 ./configure && make 的命令实现。 configure make %{?_smp_mflags} install ==>读取位于 %_builddir 构建目录下的文件并将其安装至 %_buildrootdir 目录。这些文件就是用户安装 RPM 后,最终得到的文件。注意一个奇怪的地方: 最终安装目录 不是 构建目录。通过执行类似 make install 的命令实现。 make install DESTDIR=%{buildroot} files ==>软件文件和目录 doc ==>软件说明文件 changelog ==>更新说明,星号(*) 后面应该要以时间,修改者, email 与软体版本来作为说明, 减号(-) 后面则是你要作的详细说明啰 |
除了以上这些,还是以下阶段:
- %pre 在目标系统上安装软件包之前执行的Scriptlet。注意跟%prep的区别。
- %post 在目标系统上安装软件包完成之后执行的Scriptlet。
- %preun 在从目标系统卸载软件包之前执行的Scriptlet。
- %postun 从目标系统卸载软件包完成之后执行的Scriptlet。
以下介绍一下比较重要的阶段。
%prep阶段
这个阶段里主要完成对源代码包的解压和打补丁(如果有的话),而解压时最常见到的就是一句指令:%setup -q
。这句指令可以成功执行的前提是你位于SOURCES目录下的源码包必须是name-version.tar.gz的格式才行,它还会完成后续阶段目录的切换和设置。如果在这个阶段你不用这条指令,那么后面每个阶段都要自己手动去改变相应的目录。
如果在%prep阶段,只使用了%setup
这个宏变量,代表了会运行以下操作(假设Source为cdplayer-1.0.tgz):
1 2 3 4 5 6 7 8 9 10 |
cd /usr/src/redhat/BUILD rm -rf cdplayer-1.0 gzip -dc /usr/src/redhat/SOURCES/cdplayer-1.0.tgz | tar -xvvf - if [ $? -ne 0 ]; then exit $? fi cd cdplayer-1.0 cd /usr/src/redhat/BUILD/cdplayer-1.0 chown -R root.root . chmod -R a+rX,g-w,o-w . |
可以看到,默认操作为先进入BUILD目录,然后再删除%{name}-%{version},再解压,最后再修改权限、属主等。参数-q
是指不输出运行的过程,还有其他参数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
setup -n newdir 先删除/usr/src/redhat/BUILD/newdir目录,然后将软件包解压在newdir目录;再进行这个目录进行权限设置 setup -c 先创建目录,进入这个目录后再解压。与不加参数的%setup比较,仅仅是多了mkdir 以及 cd 这2个命令 setup -D 解压缩时,不会去删除目录。与不加参数的%setup比较,少了rm -rf操作 setup -T 不进行解压的操作。与不加参数的%setup比较,少了gzip以及if判断语句 setup -b num 将第num个source文件解压缩。如果是 %setup -b 0,就会解压2次,可以使用 %setup -T -b 0,这样就只会解压一次了。但只效果跟 %setup 不加参数的效果是一样的。 setup -T -a num 先进入目录再解压第num个source文件 patch 最简单的补丁方式,自动指定patch level。 patch 0 使用第0个补丁文件,相当于%patch ?p 0。 patch -s 不显示打补丁时的信息。 patch -T 将所有打补丁时产生的输出文件删除。 *************************************/ setup -q -n %{name}-%{version} /* 如果原来只有一个“Patch:”,您增加“Patch1:”,则在SPEC文件%setup行后面的 patch -p1后面新增一行: %patch1 -p1 依此类推. */ patch0 -p1 |
实例,如果%prep的内容如下:
1 2 3 4 |
prep setup setup -T -D -a 14 setup -T -D -a 15 |
其运行的过程如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
[root@localhost SPECS]# rpmbuild -bb nginx.spec Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.N1Tdpo + umask 022 + cd /root/rpmbuild/BUILD + cd /root/rpmbuild/BUILD + rm -rf nginx-1.16.1 + /usr/bin/tar -xvvf - + /usr/bin/gzip -dc /root/rpmbuild/SOURCES/nginx-1.16.1.tar.gz ... + STATUS=0 + '[' 0 -ne 0 ']' + cd nginx-1.16.1 + /usr/bin/chmod -Rf a+rX,u+w,g-w,o-w . + cd /root/rpmbuild/BUILD + cd nginx-1.16.1 + /usr/bin/tar -xvvf - + /usr/bin/gzip -dc /root/rpmbuild/SOURCES/nginx-http-concat.tar.gz ... + STATUS=0 + '[' 0 -ne 0 ']' + /usr/bin/chmod -Rf a+rX,u+w,g-w,o-w . + cd /root/rpmbuild/BUILD + cd nginx-1.16.1 + /usr/bin/tar -xvvf - + /usr/bin/gzip -dc /root/rpmbuild/SOURCES/ngx_cache_purge.tar.gz ... |
需要注意的是,%setup -q
是指解压不输出任何提示消息,只会解压source0的文件,即第0个source文件。%setup -T -a num
先进入目录再解压第num个source文件,进入目录的意思是进入%{name}-%{version}这个目录,即spec前面定义好的Name以及Version。
https://book.huihoo.com/maximum-rpm/s1-rpm-inside-macros.html
%build阶段
这个阶段就是执行常见的configure和make操作,如果有些软件需要最先执行bootstrap之类的,可以放在configure之前来做。这个阶段我们最常见只有两条指令:
1 2 |
%configure make %{?_smp_mflags} |
这里的%configure是个宏常量,会自动将prefix设置成/usr。另外,这个宏还可以接受额外的参数,如果某些软件有某些高级特性需要开启,可以通过给%configure宏传参数来开启。如果不用 %configure这个宏的话,就需要完全手动指定configure时的配置参数了。同样地,我们也可以给make传递额外的参数,例如: make %{?_smp_mflags} CFLAGS="" …
%install阶段
这个阶段就是执行make install操作。这个阶段会在%_buildrootdir目录里建好目录结构,然后将需要打包到rpm软件包里的文件从%_builddir里拷贝到%_buildrootdir里对应的目录里。这个阶段最常见的两条指令是:
1 2 |
rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT |
其中$RPM_BUILD_ROOT也可以换成我们前面定义的BuildRoot变量,不过要写成%{buildroot}才可以,必须全部用小写,不然要报错。
如果软件有配置文件或者额外的启动脚本之类,就要手动用copy命令或者install命令你给将它也拷贝到%{buildroot}相应的目录里。用copy命令时如果目录不存在要手动建立,不然也会报错,所以推荐用install命令。
制作rpm软件包的阶段
这个阶段必须引出下面一个叫做%files的阶段。它主要用来说明会将%{buildroot}目录下的哪些文件和目录最终打包到rpm包里。
1 2 3 |
%files %defattr(-,root,root,-) %doc |
%defattr 表示的意思是: %defattr(文件权限,用户名,组名,目录权限)
,如果不牵扯到文件、目录权限的改变则一般用%defattr(-,root,root,-)这条指令来为其设置缺省权限。
关于%files阶段有两个特性要牢记:
- %{buildroot}里的所有文件都要明确被指定是否要被打包到rpm里。什么意思呢?假如,%{buildroot}目录下有4个目录a、b、c和d,在%files里仅指定a和b要打包到rpm里,如果不把c和d用exclude声明是要报错的;
- 如果声明了%{buildroot}里不存在的文件或者目录也会报错。
代表路径的宏列表
如果您看到一个不熟悉的宏,您可以使用rpm --showrc
或者 rpm --eval %{_bindir}
以下方法对其进行查看:
1 2 3 4 5 6 |
rpm --eval %{_bindir} /usr/bin [root@localhost noarch]# rpm --showrc |grep buildrootdir -14: _buildrootdir %{_topdir}/BUILDROOT -14: buildroot %{_buildrootdir}/%{name}-%{version}-%{release}.%{_arch} |
也可以直接查看/usr/lib/rpm/macros文件,以下是常见的宏:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
%{_sysconfdir} /etc %{_prefix} /usr %{_exec_prefix} %{_prefix} %{_bindir} %{_exec_prefix}/bin %{_libdir} %{_exec_prefix}/%{_lib} %{_libexecdir} %{_exec_prefix}/libexec %{_sbindir} %{_exec_prefix}/sbin %{_sharedstatedir} /var/lib %{_datarootdir} %{_prefix}/share %{_datadir} %{_datarootdir} %{_includedir} %{_prefix}/include %{_infodir} /usr/share/info %{_mandir} /usr/share/man %{_localstatedir} /var %{_initddir} %{_sysconfdir}/rc.d/init.d %{_var} /var %{_tmppath} %{_var}/tmp %{_usr} /usr %{_usrsrc} %{_usr}/src %{_lib} lib (lib64 on 64bit multilib systems) %{_docdir} %{_datadir}/doc %{buildroot} %{_buildrootdir}/%{name}-%{version}-%{release}.%{_arch} $RPM_BUILD_ROOT %{buildroot} |
要注意的是%{buildroot} 跟%{_buildrootdir}不同。%{_buildrootdir}对应的目录是~/rpmbuild/BUILDROOT;而%{buildroot}是%{_buildrootdir}/%{name}-%{version}-%{release}.%{_arch}
,有关其他内容可以参考 https://fedoraproject.org/wiki/Packaging:RPMMacros?rd=Packaging/RPMMacros#RPM_directory_macros
实例1:打包shell
可以把一个平时写的一个脚本打包成一个rpm包,spec文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
[root@localhost SPECS]# cat disk.spec Name: showdiskinfo Version: 1.0 Release: 1%{?dist} Summary: Show Raid and Disk info License: GPL URL: http://www.wumingx.cn Source0: showdiskinfo.sh BuildRequires: Requires: bash description showdiskinfo shell script. prep %setup -q build cp %_sourcedir/showdiskinfo.sh %_builddir/showdiskinfo install mkdir -p %{buildroot}/usr/local/bin install -m 755 showdiskinfo %{buildroot}/usr/local/bin files /usr/local/bin/showdiskinfo doc changelog |
开始编译:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
[root@localhost SPECS]# rpmbuild -bb disk.spec prep): /bin/sh -e /var/tmp/rpm-tmp.agda2b + umask 022 + cd /root/rpmbuild/BUILD + exit 0 build): /bin/sh -e /var/tmp/rpm-tmp.spexQx + umask 022 + cd /root/rpmbuild/BUILD + cp /root/rpmbuild/SOURCES/showdiskinfo.sh /root/rpmbuild/BUILD/showdiskinfo + exit 0 install): /bin/sh -e /var/tmp/rpm-tmp.grcfHT + umask 022 + cd /root/rpmbuild/BUILD + '[' /root/rpmbuild/BUILDROOT/showdiskinfo-1.0-1.el7.x86_64 '!=' / ']' + rm -rf /root/rpmbuild/BUILDROOT/showdiskinfo-1.0-1.el7.x86_64 ++ dirname /root/rpmbuild/BUILDROOT/showdiskinfo-1.0-1.el7.x86_64 + mkdir -p /root/rpmbuild/BUILDROOT + mkdir /root/rpmbuild/BUILDROOT/showdiskinfo-1.0-1.el7.x86_64 + mkdir -p /root/rpmbuild/BUILDROOT/showdiskinfo-1.0-1.el7.x86_64/usr/local/bin + install -m 755 showdiskinfo /root/rpmbuild/BUILDROOT/showdiskinfo-1.0-1.el7.x86_64/usr/local/bin + /usr/lib/rpm/check-buildroot + /usr/lib/rpm/redhat/brp-compress + /usr/lib/rpm/redhat/brp-strip /usr/bin/strip + /usr/lib/rpm/redhat/brp-strip-comment-note /usr/bin/strip /usr/bin/objdump + /usr/lib/rpm/redhat/brp-strip-static-archive /usr/bin/strip + /usr/lib/rpm/brp-python-bytecompile /usr/bin/python 1 + /usr/lib/rpm/redhat/brp-python-hardlink + /usr/lib/rpm/redhat/brp-java-repack-jars Processing files: showdiskinfo-1.0-1.el7.x86_64 Provides: showdiskinfo = 1.0-1.el7 showdiskinfo(x86-64) = 1.0-1.el7 Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(FileDigests) <= 4.6.0-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1 Requires: /bin/bash Checking for unpackaged file(s): /usr/lib/rpm/check-files /root/rpmbuild/BUILDROOT/showdiskinfo-1.0-1.el7.x86_64 Wrote: /root/rpmbuild/RPMS/x86_64/showdiskinfo-1.0-1.el7.x86_64.rpm clean): /bin/sh -e /var/tmp/rpm-tmp.4uHq3D + umask 022 + cd /root/rpmbuild/BUILD + /usr/bin/rm -rf /root/rpmbuild/BUILDROOT/showdiskinfo-1.0-1.el7.x86_64 + exit 0 |
可以看到编译成功了,文件保存在Wrote: /root/rpmbuild/RPMS/x86_64/showdiskinfo-1.0-1.el7.x86_64.rpm
下,开始查看:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
[root@localhost SPECS]# cd ../RPMS/x86_64/ [root@localhost x86_64]# rpm -qpi showdiskinfo-1.0-1.el7.x86_64.rpm Name : showdiskinfo Version : 1.0 Release : 1.el7 Architecture: x86_64 Install Date: (not installed) Group : Unspecified Size : 38390 License : GPL Signature : (none) Source RPM : showdiskinfo-1.0-1.el7.src.rpm Build Date : Fri 08 Mar 2019 06:41:42 PM EST Build Host : localhost Relocations : (not relocatable) URL : http://www.wumingx.cn Summary : Show Raid and Disk info Description : showdiskinfo shell script. [root@localhost x86_64]# rpm -qpl showdiskinfo-1.0-1.el7.x86_64.rpm /usr/local/bin/showdiskinfo 开始安装 [root@localhost x86_64]# rpm -ivh showdiskinfo-1.0-1.el7.x86_64.rpm Preparing... ################################# [100%] Updating / installing... 1:showdiskinfo-1.0-1.el7 ################################# [100%] [root@localhost x86_64]# ll /usr/local/bin/ total 40 -rwxr-xr-x. 1 root root 38390 Mar 8 18:41 showdiskinfo [root@localhost x86_64]# showdiskinfo no raid |
此内容参考了 https://rpm-packaging-guide.github.io/#hello-world ,可以阅读原版。
实例2:打包main
此代码来源鸟哥私房菜,先来处理原始码的部份:
1 2 3 4 5 6 |
[root@study ~]# cd /root/rpmbuild/SOURCES [root@study SOURCES]# wget http://linux.vbird.org/linux_basic/0520source/main-0.1.tgz [root@study SOURCES]# wget http ://linux.vbird.org/linux_basic/0520source/main_0.1_to_0.2.patch [root@study SOURCES]# ll main* -rw-r--r--. 1 root root 703 Sep 4 14:47 main-0.1.tgz -rw-r--r--. 1 root root 1538 Sep 4 14:51 main_0.1_to_0.2.patch |
到SPECS目录下创建main.spec文件,建议使用vim创建,会自动生成格式。也可以用rpmdev-newspec -o Name-version.spec
命令来生成SPEC文件的模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
[root@localhost SPECS]# cat main.spec Name: main Version: 0.1 Release: 1%{?dist} Summary: Shows sin and cos value Group: Scientific Support License: GPLv2 URL: http://www.fangdm.com/ Source0: main-0.1.tgz Patch0: main_0.1_to_0.2.patch BuildRequires: Requires: description This package will let you input your name and calculate sin cos value. prep setup -q patch0 -p1 build make clean main install mkdir -p %{buildroot}/usr/local/bin install -m 755 main %{buildroot}/usr/local/bin files /usr/local/bin/main doc changelog * Wed Sep 09 2015 VBird Tsai <vbird@mail.vbird.idv.tw> 0.2 - build the program |
然后就直接编译rpmbuild -ba main.spec
,再安装rpm -ivh main-0.1-1.el7.x86_64.rpm
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
[root@localhost x86_64]# rpm -qi main Name : main Version : 0.1 Release : 1.el7 Architecture: x86_64 Install Date: Thu 07 Mar 2019 05:42:50 PM EST Group : Scientific Support Size : 7272 License : GPLv2 Signature : (none) Source RPM : main-0.1-1.el7.src.rpm Build Date : Thu 07 Mar 2019 05:42:07 PM EST Build Host : localhost Relocations : (not relocatable) URL : http://www.fangdm.com/ Summary : Shows sin and cos value Description : This package will let you input your name and calculate sin cos value. |
实例3:打包hello
使用区域语言(Locale)文件的程序应遵循 处理 i18n 文件的建议方法:
- 在 %install 步骤中找出文件名: %find_lang ${name}
- 添加必要的编译依赖: BuildRequires: gettext
- 使用找到的文件名: %files -f ${name}.lang
%find_lang此宏将找到属于您的包的所有语言环境文件(按名称),并将此列表放在一个文件中。然后,您可以使用该文件包含所有语言环境。
1 2 3 4 |
[root@localhost SPECS]# rpm --eval %find_lang /usr/lib/rpm/find-lang.sh /root/rpmbuild/BUILDROOT/%{name}-%{version}-%{release}.x86_64 [root@localhost SPECS]# rpm --eval %make_install /usr/bin/make install DESTDIR=/root/rpmbuild/BUILDROOT/%{name}-%{version}-%{release}.x86_64 |
%find_lang %{name}
在这个spec里面等价于/usr/lib/rpm/find-lang.sh /root/rpmbuild/BUILDROOT/hello-2.10-1.el7.x86_64 hello
而引用的方法是:%files -f %{name}.lang
即可。
%make_install
是等价于make install DESTDIR=%{buildroot}
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
[root@localhost SPECS]# cat hello.spec Name: hello Version: 2.10 Release: 1%{?dist} Summary: The "Hello World" program from GNU License: GPLv3 URL: http://ftp.gnu.org/gnu/hello/ Source0: hello-2.10.tar.gz BuildRequires: gettext Requires: description The "Hello World" program, done with all bells and whistles of a proper FOSS project, including configuration, build, internationalization, help files, etc. prep setup -q build configure make %{?_smp_mflags} install make_install find_lang %{name} rm -f %{buildroot}/%{_infodir}/dir post /sbin/install-info %{_infodir}/%{name}.info %{_infodir}/dir || : preun if [ $1 = 0 ] ; then /sbin/install-info --delete %{_infodir}/%{name}.info %{_infodir}/dir || : fi files -f %{name}.lang {_bindir}/%{name} doc {_infodir}/%{name}.info.* {_mandir}/man1/%{name}.1.* changelog |
然后直接rpmbuild -bb hello.spec
进行编译,此实例来源于:https://fedoraproject.org/wiki/How_to_create_a_GNU_Hello_RPM_package/zh-cn
实例4:打包smartmontools
smartmontools 7.0已经支持json格式的输出,对于采集的话,有很大的优势。目前在centos官方上面可以找到centos7的包,如https://cbs.centos.org/koji/buildinfo?buildID=25069,但是还没有centos6的,所以需要自己写一个spec。
访问https://cbs.centos.org/koji/buildinfo?buildID=25069,先下载src.rpm包,然后`rpm -ivh smartmontools-7.0-3.el7.src.rpm`就可以提取到smartmontools.spec,这个是centos7下面环境编译的,不能直接使用。需要再下载 http://yum.aclub.net/pub/linux/centos/6/umask/SRPMS/smartmontools-6.3-1.el6.src.rpm smartmontools 6.x的版本,就可以对比开工改写spec文件了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
[root@7ftbv7mdz7cdpc ~]# cat smartmontools.spec Summary: Tools for monitoring SMART capable hard disks Name: smartmontools Version: 7.0 Release: 3%{?dist} Epoch: 1 License: GPLv2+ URL: http://smartmontools.sourceforge.net/ Source0: http://downloads.sourceforge.net/%{name}/%{name}-%{version}.tar.gz Source0: %{name}-%{version}.tar.gz Source1: smartd.initd Source2: smartmontools.sysconf Source4: smartdnotify semi-automatic update of drivedb.h global UrlSource5 https://sourceforge.net/p/smartmontools/code/HEAD/tree/trunk/smartmontools/drivedb.h?format=raw Source5: drivedb.h fedora/rhel specific Patch1: smartmontools-5.38-defaultconf.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Requires: fileutils chkconfig initscripts BuildRequires: readline-devel ncurses-devel automake util-linux groff gettext BuildRequires: libselinux-devel libcap-ng-devel description The smartmontools package contains two utility programs (smartctl and smartd) to control and monitor storage systems using the Self- Monitoring, Analysis and Reporting Technology System (SMART) built into most modern ATA and SCSI hard disks. In many cases, these utilities will provide advanced warning of disk degradation and failure. prep setup -q patch1 -p1 -b .defaultconf update SOURCE5 on maintainer's machine prior commiting, there's no internet connection on builders curl %{UrlSource5} -o %{SOURCE5} ||: cp %{SOURCE5} . build autoreconf -i configure --with-selinux --with-libcap-ng=yes --with-systemdsystemunitdir=no --with-cxx11-option=no ifarch sparc64 make CXXFLAGS="$RPM_OPT_FLAGS -fPIE -fno-strict-aliasing" LDFLAGS="-pie -Wl,-z,relro,-z,now" else make CXXFLAGS="$RPM_OPT_FLAGS -fpie -fno-strict-aliasing" LDFLAGS="-pie -Wl,-z,relro,-z,now" endif install rm -rf $RPM_BUILD_ROOT make DESTDIR=$RPM_BUILD_ROOT install rm -f examplescripts/Makefile* chmod a-x -R examplescripts/* mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/%{name}/smartd_warning.d install -D -p -m 755 %{SOURCE1} $RPM_BUILD_ROOT%{_sysconfdir}/rc.d/init.d/smartd install -D -p -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/smartmontools install -D -p -m 755 %{SOURCE4} $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/smartd_warning.d/smartdnotify rm -rf $RPM_BUILD_ROOT%{_docdir}/%{name} mkdir -p $RPM_BUILD_ROOT%{_sharedstatedir}/%{name} clean rm -rf $RPM_BUILD_ROOT preun if [ "$1" = "0" ] ; then /sbin/service smartd stop >/dev/null 2>&1 /sbin/chkconfig --del smartd fi post /sbin/chkconfig --add smartd files defattr(-,root,root,-) doc AUTHORS ChangeLog COPYING INSTALL NEWS README doc TODO examplescripts smartd.conf {_sbindir}/smartd {_sbindir}/update-smart-drivedb {_sbindir}/smartctl {_initddir}/smartd {_mandir}/man?/smart*.* {_mandir}/man?/update-smart*.* {_datadir}/%{name} {_sharedstatedir}/%{name} dir %{_sysconfdir}/%name dir %{_sysconfdir}/%name/smartd_warning.d config(noreplace) %{_sysconfdir}/smartd.conf config(noreplace) %{_sysconfdir}/smartd_warning.sh config(noreplace) %{_sysconfdir}/%{name}/smartd_warning.d/smartdnotify config(noreplace) %{_sysconfdir}/sysconfig/smartmontools changelog * Thu Sep 26 2019 fangdm <fangdm@wangsu.com> - 1:7.0-3 - create smartmontools 7.0 base on centos 6 |
注意,Source这几个文件一定要存在,从上可以得知,加入了启动脚本、配置文件等,准备好了之后就可以使用rpmbuild -bb smartmontools.spec
来编译,经过多次失败后,根据报错信息进行调整之后,终于编译成功了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
[root@7ftbv7mdz7cdpc SPECS]# rpm -qp --changelog /root/rpmbuild/RPMS/x86_64/smartmontools-7.0-3.el6.x86_64.rpm * Thu Sep 26 2019 fangdm <fangdm@wangsu.com> - 1:7.0-3 - create smartmontools 7.0 base on centos 6 [root@7ftbv7mdz7cdpc SPECS]# rpm -qpi /root/rpmbuild/RPMS/x86_64/smartmontools-7.0-3.el6.x86_64.rpm Name : smartmontools Relocations: (not relocatable) Version : 7.0 Vendor: (none) Release : 3.el6 Build Date: Thu 26 Sep 2019 10:53:19 PM CST Install Date: (not installed) Build Host: 7ftbv7mdz7cdpc Group : System Environment/Base Source RPM: smartmontools-7.0-3.el6.src.rpm Size : 2081911 License: GPLv2+ Signature : (none) URL : http://smartmontools.sourceforge.net/ Summary : Tools for monitoring SMART capable hard disks Description : The smartmontools package contains two utility programs (smartctl and smartd) to control and monitor storage systems using the Self- Monitoring, Analysis and Reporting Technology System (SMART) built into most modern ATA and SCSI hard disks. In many cases, these utilities will provide advanced warning of disk degradation and failure. |
另外,在%preun阶段有使用了if [ "$1" = "0" ]
,表示的意思是uninstall,如下图:
实例5:打包nginx
用tar包打包成rpm的最简单的方法就是在网上找到相对应src.rpm的版本,这里面有包括了spec文件,可以少走很多弯路。nginx官方在释放tar包之后,也会相应提供的rpm以及srpm包,这次我们先在 http://nginx.org/packages/centos/7/SRPMS/ 下载好nginx-1.16.1-1.el7.ngx.src.rpm,使用rpm -ivh nginx-1.16.1-1.el7.ngx.src.rpm
进行安装。有生成了如下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
[root@localhost rpmbuild]# tree . |-- BUILD |-- BUILDROOT |-- RPMS |-- SOURCES | |-- COPYRIGHT | |-- logrotate | |-- nginx-1.16.1.tar.gz | |-- nginx-debug.service | |-- nginx-debug.sysconf | |-- nginx.check-reload.sh | |-- nginx.conf | |-- nginx.init.in | |-- nginx.service | |-- nginx.suse.logrotate | |-- nginx.sysconf | |-- nginx.upgrade.sh | `-- nginx.vh.default.conf |-- SPECS | `-- nginx.spec `-- SRPMS |
主要是SPECS以及SOURCES这些文件。查看nginx.spec之后,大部分都有写好了,并且都兼容了centos 6/7。添加了gperftools GeoIP-devel ngx_cache_purge nginx-http-concat这四个模块,修改如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 |
[root@localhost SPECS]# cat nginx.spec define nginx_home %{_localstatedir}/cache/nginx define nginx_user nginx define nginx_group nginx define nginx_loggroup adm distribution specific definitions define use_systemd (0%{?rhel} >= 7 || 0%{?fedora} >= 19 || 0%{?suse_version} >= 1315 || 0%{?amzn} >= 2) if %{use_systemd} BuildRequires: systemd Requires(post): systemd Requires(preun): systemd Requires(postun): systemd endif if 0%{?rhel} define _group System Environment/Daemons endif if 0%{?rhel} == 6 Requires(pre): shadow-utils Requires: initscripts >= 8.36 Requires(post): chkconfig Requires: openssl >= 1.0.1 BuildRequires: openssl-devel >= 1.0.1 endif if 0%{?rhel} == 7 define epoch 1 Epoch: %{epoch} Requires(pre): shadow-utils gperftools GeoIP-devel Requires: openssl >= 1.0.2 BuildRequires: openssl-devel >= 1.0.2 BuildRequires: GeoIP-devel gperftools define dist .el7 endif if 0%{?rhel} == 8 define epoch 1 Epoch: %{epoch} Requires(pre): shadow-utils BuildRequires: openssl-devel >= 1.1.1 define _debugsource_template %{nil} endif if 0%{?suse_version} >= 1315 define _group Productivity/Networking/Web/Servers define nginx_loggroup trusted Requires(pre): shadow BuildRequires: libopenssl-devel define _debugsource_template %{nil} endif end of distribution specific definitions define main_version 1.16.1 define main_release 1%{?dist}.ngx define bdir %{_builddir}/%{name}-%{main_version} define WITH_CC_OPT $(echo %{optflags} $(pcre-config --cflags)) -fPIC define WITH_LD_OPT -Wl,-z,relro -Wl,-z,now -pie define BASE_CONFIGURE_ARGS $(echo "--prefix=%{_sysconfdir}/nginx --sbin-path=%{_sbindir}/nginx --modules-path=%{_libdir}/nginx/modules --conf-path=%{_sysconfdir}/nginx/nginx.conf --error-log-path=%{_localstatedir}/log/nginx/error.log --http-log-path=%{_localstatedir}/log/nginx/access.log --pid-path=%{_localstatedir}/run/nginx.pid --lock-path=%{_localstatedir}/run/nginx.lock --http-client-body-temp-path=%{_localstatedir}/cache/nginx/client_temp --http-proxy-temp-path=%{_localstatedir}/cache/nginx/proxy_temp --http-fastcgi-temp-path=%{_localstatedir}/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=%{_localstatedir}/cache/nginx/uwsgi_temp --http-scgi-temp-path=%{_localstatedir}/cache/nginx/scgi_temp --user=%{nginx_user} --group=%{nginx_group} --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module") Summary: High performance web server Name: nginx Version: %{main_version} Release: %{main_release} Vendor: Nginx, Inc. URL: http://nginx.org/ Group: %{_group} Source0: http://nginx.org/download/%{name}-%{version}.tar.gz Source1: logrotate Source2: nginx.init.in Source3: nginx.sysconf Source4: nginx.conf Source5: nginx.vh.default.conf Source7: nginx-debug.sysconf Source8: nginx.service Source9: nginx.upgrade.sh Source10: nginx.suse.logrotate Source11: nginx-debug.service Source12: COPYRIGHT Source13: nginx.check-reload.sh Source14: nginx-http-concat.tar.gz Source15: ngx_cache_purge.tar.gz License: 2-clause BSD-like license BuildRoot: %{_tmppath}/%{name}-%{main_version}-%{main_release}-root BuildRequires: zlib-devel BuildRequires: pcre-devel Provides: webserver description nginx [engine x] is an HTTP and reverse proxy server, as well as a mail proxy server. if 0%{?suse_version} >= 1315 debug_package endif prep setup setup -T -D -a 14 setup -T -D -a 15 cp %{SOURCE2} . sed -e 's|%%DEFAULTSTART%%|2 3 4 5|g' -e 's|%%DEFAULTSTOP%%|0 1 6|g' \ -e 's|%%PROVIDES%%|nginx|g' < %{SOURCE2} > nginx.init sed -e 's|%%DEFAULTSTART%%||g' -e 's|%%DEFAULTSTOP%%|0 1 2 3 4 5 6|g' \ -e 's|%%PROVIDES%%|nginx-debug|g' < %{SOURCE2} > nginx-debug.init build ./configure %{BASE_CONFIGURE_ARGS} \ --with-cc-opt="%{WITH_CC_OPT}" \ --with-ld-opt="%{WITH_LD_OPT}" \ --with-debug \ --with-google_perftools_module \ --add-module=ngx_cache_purge \ --add-module=nginx-http-concat \ --with-http_geoip_module make %{?_smp_mflags} {__mv} %{bdir}/objs/nginx \ %{bdir}/objs/nginx-debug ./configure %{BASE_CONFIGURE_ARGS} \ --with-cc-opt="%{WITH_CC_OPT}" \ --with-ld-opt="%{WITH_LD_OPT}" make %{?_smp_mflags} install {__rm} -rf $RPM_BUILD_ROOT {__make} DESTDIR=$RPM_BUILD_ROOT INSTALLDIRS=vendor install {__mkdir} -p $RPM_BUILD_ROOT%{_datadir}/nginx {__mv} $RPM_BUILD_ROOT%{_sysconfdir}/nginx/html $RPM_BUILD_ROOT%{_datadir}/nginx/ {__rm} -f $RPM_BUILD_ROOT%{_sysconfdir}/nginx/*.default {__rm} -f $RPM_BUILD_ROOT%{_sysconfdir}/nginx/fastcgi.conf {__mkdir} -p $RPM_BUILD_ROOT%{_localstatedir}/log/nginx {__mkdir} -p $RPM_BUILD_ROOT%{_localstatedir}/run/nginx {__mkdir} -p $RPM_BUILD_ROOT%{_localstatedir}/cache/nginx {__mkdir} -p $RPM_BUILD_ROOT%{_libdir}/nginx/modules cd $RPM_BUILD_ROOT%{_sysconfdir}/nginx && \ %{__ln_s} ../..%{_libdir}/nginx/modules modules && cd - {__mkdir} -p $RPM_BUILD_ROOT%{_datadir}/doc/%{name}-%{main_version} {__install} -m 644 -p %{SOURCE12} \ $RPM_BUILD_ROOT%{_datadir}/doc/%{name}-%{main_version}/ {__mkdir} -p $RPM_BUILD_ROOT%{_sysconfdir}/nginx/conf.d {__rm} $RPM_BUILD_ROOT%{_sysconfdir}/nginx/nginx.conf {__install} -m 644 -p %{SOURCE4} \ $RPM_BUILD_ROOT%{_sysconfdir}/nginx/nginx.conf {__install} -m 644 -p %{SOURCE5} \ $RPM_BUILD_ROOT%{_sysconfdir}/nginx/conf.d/default.conf {__mkdir} -p $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig {__install} -m 644 -p %{SOURCE3} \ $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/nginx {__install} -m 644 -p %{SOURCE7} \ $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/nginx-debug {__install} -p -D -m 0644 %{bdir}/objs/nginx.8 \ $RPM_BUILD_ROOT%{_mandir}/man8/nginx.8 if %{use_systemd} install systemd-specific files {__mkdir} -p $RPM_BUILD_ROOT%{_unitdir} {__install} -m644 %SOURCE8 \ $RPM_BUILD_ROOT%{_unitdir}/nginx.service {__install} -m644 %SOURCE11 \ $RPM_BUILD_ROOT%{_unitdir}/nginx-debug.service {__mkdir} -p $RPM_BUILD_ROOT%{_libexecdir}/initscripts/legacy-actions/nginx {__install} -m755 %SOURCE9 \ $RPM_BUILD_ROOT%{_libexecdir}/initscripts/legacy-actions/nginx/upgrade {__install} -m755 %SOURCE13 \ $RPM_BUILD_ROOT%{_libexecdir}/initscripts/legacy-actions/nginx/check-reload else install SYSV init stuff {__mkdir} -p $RPM_BUILD_ROOT%{_initrddir} {__install} -m755 nginx.init $RPM_BUILD_ROOT%{_initrddir}/nginx {__install} -m755 nginx-debug.init $RPM_BUILD_ROOT%{_initrddir}/nginx-debug endif install log rotation stuff {__mkdir} -p $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d if 0%{?suse_version} {__install} -m 644 -p %{SOURCE10} \ $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/nginx else {__install} -m 644 -p %{SOURCE1} \ $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/nginx endif {__install} -m755 %{bdir}/objs/nginx-debug \ $RPM_BUILD_ROOT%{_sbindir}/nginx-debug check {__rm} -rf $RPM_BUILD_ROOT/usr/src cd %{bdir} grep -v 'usr/src' debugfiles.list > debugfiles.list.new && mv debugfiles.list.new debugfiles.list cat /dev/null > debugsources.list if 0%{?suse_version} >= 1500 cat /dev/null > debugsourcefiles.list endif clean {__rm} -rf $RPM_BUILD_ROOT files defattr(-,root,root) {_sbindir}/nginx {_sbindir}/nginx-debug dir %{_sysconfdir}/nginx dir %{_sysconfdir}/nginx/conf.d {_sysconfdir}/nginx/modules config(noreplace) %{_sysconfdir}/nginx/nginx.conf config(noreplace) %{_sysconfdir}/nginx/conf.d/default.conf config(noreplace) %{_sysconfdir}/nginx/mime.types config(noreplace) %{_sysconfdir}/nginx/fastcgi_params config(noreplace) %{_sysconfdir}/nginx/scgi_params config(noreplace) %{_sysconfdir}/nginx/uwsgi_params config(noreplace) %{_sysconfdir}/nginx/koi-utf config(noreplace) %{_sysconfdir}/nginx/koi-win config(noreplace) %{_sysconfdir}/nginx/win-utf config(noreplace) %{_sysconfdir}/logrotate.d/nginx config(noreplace) %{_sysconfdir}/sysconfig/nginx config(noreplace) %{_sysconfdir}/sysconfig/nginx-debug if %{use_systemd} {_unitdir}/nginx.service {_unitdir}/nginx-debug.service dir %{_libexecdir}/initscripts/legacy-actions/nginx {_libexecdir}/initscripts/legacy-actions/nginx/* else {_initrddir}/nginx {_initrddir}/nginx-debug endif attr(0755,root,root) %dir %{_libdir}/nginx attr(0755,root,root) %dir %{_libdir}/nginx/modules dir %{_datadir}/nginx dir %{_datadir}/nginx/html {_datadir}/nginx/html/* attr(0755,root,root) %dir %{_localstatedir}/cache/nginx attr(0755,root,root) %dir %{_localstatedir}/log/nginx dir %{_datadir}/doc/%{name}-%{main_version} doc %{_datadir}/doc/%{name}-%{main_version}/COPYRIGHT {_mandir}/man8/nginx.8* pre Add the "nginx" user getent group %{nginx_group} >/dev/null || groupadd -r %{nginx_group} getent passwd %{nginx_user} >/dev/null || \ useradd -r -g %{nginx_group} -s /sbin/nologin \ -d %{nginx_home} -c "nginx user" %{nginx_user} exit 0 post Register the nginx service if [ $1 -eq 1 ]; then if %{use_systemd} /usr/bin/systemctl preset nginx.service >/dev/null 2>&1 ||: /usr/bin/systemctl preset nginx-debug.service >/dev/null 2>&1 ||: else /sbin/chkconfig --add nginx /sbin/chkconfig --add nginx-debug endif # print site info cat <<BANNER ---------------------------------------------------------------------- Thanks for using nginx! Please find the official documentation for nginx here: * http://nginx.org/en/docs/ Please subscribe to nginx-announce mailing list to get the most important news about nginx: * http://nginx.org/en/support.html Commercial subscriptions for nginx are available on: * http://nginx.com/products/ ---------------------------------------------------------------------- BANNER # Touch and set permisions on default log files on installation if [ -d %{_localstatedir}/log/nginx ]; then if [ ! -e %{_localstatedir}/log/nginx/access.log ]; then touch %{_localstatedir}/log/nginx/access.log %{__chmod} 640 %{_localstatedir}/log/nginx/access.log %{__chown} nginx:%{nginx_loggroup} %{_localstatedir}/log/nginx/access.log fi if [ ! -e %{_localstatedir}/log/nginx/error.log ]; then touch %{_localstatedir}/log/nginx/error.log %{__chmod} 640 %{_localstatedir}/log/nginx/error.log %{__chown} nginx:%{nginx_loggroup} %{_localstatedir}/log/nginx/error.log fi fi fi preun if [ $1 -eq 0 ]; then if %use_systemd /usr/bin/systemctl --no-reload disable nginx.service >/dev/null 2>&1 ||: /usr/bin/systemctl stop nginx.service >/dev/null 2>&1 ||: else /sbin/service nginx stop > /dev/null 2>&1 /sbin/chkconfig --del nginx /sbin/chkconfig --del nginx-debug endif fi postun if %use_systemd /usr/bin/systemctl daemon-reload >/dev/null 2>&1 ||: endif if [ $1 -ge 1 ]; then /sbin/service nginx status >/dev/null 2>&1 || exit 0 /sbin/service nginx upgrade >/dev/null 2>&1 || echo \ "Binary upgrade failed, please check nginx's error.log" fi changelog * Tue Sep 30 2019 fangdm <fangdm@wangsu.com> - Add modules nginx-http-concat and ngx_cache_purge * Tue Aug 13 2019 Andrei Belov <defan@nginx.com> - 1.16.1 |
编译完成之后,查看changelog,是成功了。
1 2 3 4 5 6 |
[root@localhost SPECS]# rpm --changelog -qp /root/rpmbuild/RPMS/x86_64/nginx-1.16.1-1.el7.ngx.x86_64.rpm * Mon Sep 30 2019 fangdm <fangdm@wangsu.com> - Add modules nginx-http-concat and ngx_cache_purge * Tue Aug 13 2019 Andrei Belov <defan@nginx.com> - 1.16.1 |
fpm打包方法
使用fpm这个方式也是可以将tar打包为rpm包,其打包流程大致是这样的:
- 编译安装被打包软件,指定安装的临时目录,如指定
--prefix=/fpmbulid
- 创建安装脚本、卸载脚本
- 安装FPM工具
- 使用fpm打包
具体的细节,请参考:FPM,更快捷方便的制作rpm包
参考资料
官方文档:https://rpm-packaging-guide.github.io/
RPM打包原理、示例、详解及备查 https://blog.csdn.net/get_set/article/details/53453320
RPM 包制作(详细):https://jin-yang.github.io/post/linux-create-rpm-package.html
spec文件查找:https://git.centos.org/
rpm Scriptlets变量说明: https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/
spec中的 Install命令:https://www.cnblogs.com/wangziyi0513/p/10252458.html
一、如果您发现本站侵害了相关版权,请附上本站侵权链接和您的版权证明一并发送至邮箱:yehes#qq.com(#替换为@)我们将会在五天内处理并断开该文章下载地址。
二、本站所有资源来自互联网整理收集,全部内容采用撰写共用版权协议,要求署名、非商业用途和相同方式共享,如转载请也遵循撰写共用协议。
三、根据署名-非商业性使用-相同方式共享 (by-nc-sa) 许可协议规定,只要他人在以原作品为基础创作的新作品上适用同一类型的许可协议,并且在新作品发布的显著位置,注明原作者的姓名、来源及其采用的知识共享协议,与该作品在本网站的原发地址建立链接,他人就可基于非商业目的对原作品重新编排、修改、节选或者本人的作品为基础进行创作和发布。
四、基于原作品创作的所有新作品都要适用同一类型的许可协议,因此适用该项协议, 对任何以他人原作为基础创作的作品自然同样都不得商业性用途。
五、根据二〇〇二年一月一日《计算机软件保护条例》规定:为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可不经软件著作权人许可,无需向其支付报酬!
六、鉴此,也望大家按此说明转载和分享资源!本站提供的所有信息、教程、软件版权归原公司所有,仅供日常使用,不得用于任何商业用途,下载试用后请24小时内删除,因下载本站资源造成的损失,全部由使用者本人承担!