文章写于 2021-08-02
,防止排列在前面,所以 markdown 里的时间改成 2017-05-15
。
rpm 一些知识 建议起个 centos:7
的容器里去制作
Linux 里的 so 用白话说,就是类似于 windows 的 dll 文件,通常是底层库,或者经常用到的 c 函数。比如说 curl 命令和 wget 命令,他们很多的底层例如 http 请求,dns 解析,hosts 解析这块逻辑是一样的。如果他们全部打包在二进制文件里(也就是静态编译)会造成二进制体积很大(golang 一般都是静态编译的)。如果共用(共用的一个其中原因是因为早期的系统硬盘容量很小)的话体积会很小,所以安装 rpm 的时候一般会检查依赖。
rpm 制作目录 rpm 包分为两种,rpm 和 srpm。前者基本是打包文件(编译好的二进制文件例如/usr/sbin/nginx、lograte、conf、和 systemd 文件),后者里面有源码包,安装的时候会编译安装,通常的 rpm 包是代指前者。
制作 rpm 包需要以下目录:
1 2 3 4 5 6 BUILD # 编译 rpm 包的临时目录 BUILDROOT # 虚拟安装目录,即在整个 install 的过程中临时安装到这个目录,把这个目录当作根来用的,所以在这个目录下的文件,才是真正的目录文件。最终, Spec 文件中最后有清理阶段,这个目录中的内容将被删除 RPMS # 制作完成后的rpm包存放目录,会以架构名存放,例如 RPMS/{aarch64,x86_64}/xxx.rpm SOURCES # 存放源文件,配置文件,补丁文件等放置的目录,如果是 srpm 的话,一般这个目录是有源码,不是 srpm 的话,里面一般有编译好的二进制文件。 SPECS # 核心文件,里面的文件描述 rpm 包的制作和每个步骤怎么执行 SRPMS # srpm 包生成存放文件
这些目录可以通过 rpmdevtools
包里的命令 rpmdev-setuptree
创建,rpmdev-setuptree
实际上是一个脚本。它会生成文件 ~/.rpmmacros
(如果文件里没有定义 %_topdir
则写入%_topdir %(echo $HOME)/rpmbuild
)然后在 %_topdir
目录下创建上面的制作目录。也可以手动创建目录。安装 rpmbuild 的包:
1 2 yum install -y rpm-build \ rpmdevtools
创建目录:
1 2 3 4 mkdir -p /root/rpmbuild/ cd /root/rpmbuild/ mkdir -p {BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
另外后文的 spec 文件里用了很多 __xxx
的,可以通过默认的宏文件查看,例如
1 2 3 4 5 6 7 8 $ rpmbuild --showrc | grep topdir -14: _builddir %{_topdir}/BUILD -14: _buildrootdir %{_topdir}/BUILDROOT -14: _rpmdir %{_topdir}/RPMS -14: _sourcedir %{_topdir}/SOURCES -14: _specdir %{_topdir}/SPECS -14: _srcrpmdir %{_topdir}/SRPMS -14: _topdir %{getenv:HOME}/rpmbuild
一个下划线是环境有关,两个下划线一般是命令。也推荐使用内置的宏,因为每个系统的命令路径和存放路径不同。
实践 最小模板讲解 比如说文件 SPECS/xxx.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 Name: hellorpm #名字为源码tar.gz 包的名字 Version: 1.0.0 #版本号,一定要与tar.gz包的一致哦 Release: 1%{?dist} #释出号,也就是第几次制作rpm Summary: helloword #软件包简介,最好不要超过50字符 License: GPL #许可,GPL还是BSD等 URL: #可以写一个网址 Packager: abel Source0: %{name}-%{version}.tar.gz #定义用到的source,也就是你的源码 BuildRoot: %_topdir/BUILDROOT #这个是软件make install 的测试安装目录. BuildRequires: gcc,make #制作过程中用到的软件包 Requires: python-apscheduler >= 2.1.2-1.el7,python-daemon >= 1.6-1.el7 #软件运行依赖的软件包,也可以指定最低版本如 bash >= 1.1.1 %description #描述,随便写 %prep #打包开始 %setup -q #这个作用静默模式解压所有 Source 并cd %build #编译制作阶段,主要目的就是编译,如果不用编译就为空 ./configure \ %{?_smp_mflags} #make后面的意思是:如果就多处理器的话make时并行编译 %install #安装阶段 rm -rf %{buildroot} #先删除原来的安装的,如果你不是第一次安装的话 cp -rp %_topdir/BUILD/%{name}-%{version}/* $RPM_BUILD_ROOT #将需要需要打包的文件从BUILD 文件夹中拷贝到BUILDROOT文件夹下。 #下面的几步pre、post、preun、postun 没必要可以不写 %pre #rpm安装前制行的脚本 %post #安装后执行的脚本 %preun #卸载前执行的脚本 %postun #卸载后执行的脚本 %clean #清理段,删除buildroot rm -rf %{buildroot} %files #rpm要包含的文件 %defattr (-,root,root,-) #设定默认权限,如果下面没有指定权限,则继承默认 /etc/hello/word/helloword.c #将你需要打包的文件或目录写下来 ### 7.chagelog section 改变日志段 %changelog
打包 1 rpmbuild -bb SPECS/xxx.spec
单步执行选项。可以先 rpmbuild -bp
,再 -bc
再 -bi
如果没问题,rpmbuild -ba
生成 src 包与二进制包。
1 2 3 4 5 6 7 -ba 既生成src.rpm又生成二进制rpm -bs 只生成src的rpm -bb 只生二进制的rpm -bp 执行到pre -bc 执行到 build段 -bi 执行install段 ,有 %files 则也会处理 files, %doc 同理 -bl 检测有文件没包含
nginx 做示例 大多数参考来源于 nginx-1.19.10-1.el7.ngx.src.rpm 使用 rpm2cpio ../nginx-1.19.10-1.el7.ngx.src.rpm | cpio -div
解开后里面的 nginx.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 cat > SOURCES/nginx.conf << 'EOF' user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf; } EOF cat > SOURCES/nginx.default.conf << 'EOF' server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } EOF
下载源码文件:
1 2 3 cd SOURCES wget https://nginx.org/download/nginx-1.19.10.tar.gz cd -
开始编写:
内容为下面的,一般最开始是定义一些变量。所有 %define xxx yyy aaa
都可以通过运行 rpmbuild
的时候使用 --define 'xxx yyy aaa'
表示 xxx='yyy aaa'
,然后可以使用 %{xxx}
即可。 也可以调用 shell, 就像下面的 %define _topdir %(echo $PWD)
, 也可以获取环境变量 %define _topdir %{getenv:HOME}/rpmbuild
。
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 # 定义目录的变量,因为我这里不是`~/rpmbuild`。也可以用 rpmbuild 运行时候 rpmbuild --define '_topdir `pwd`' # 定义为 pwd 的话这个遇到问题,Dest dir longer than base dir is not supported # ref: https://bugzilla.redhat.com/show_bug.cgi?id=1427970 # %define _topdir %(echo $PWD) %define _prefix /usr/local/nginx //预定义的prefix目录 %define nginx_home %{_localstatedir}/cache/nginx %define nginx_user nginx %define nginx_group nginx %define nginx_loggroup adm %define nginx_debug 0 %if 0%{?rhel} == 7 %define epoch 1 Epoch: %{epoch} Requires(pre): shadow-utils Requires: openssl >= 1.0.2 BuildRequires: openssl-devel >= 1.0.2 %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 %define base_version 1.19.10 %define base_release 1%{?dist}.ngx %define bdir %{_builddir}/%{name}-%{base_version} %define WITH_CC_OPT $(echo %{optflags} $(pcre-config --cflags)) -fPIC %define WITH_LD_OPT -Wl,-z,relro -Wl,-z,now -pie # http://nginx.org/en/docs/configure.html %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-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module") # 介绍,看到有人说建议不超过 50 字符 Summary: High performance web server # 软件包的名字,后面可以使用 %{name} 的方式引用 Name: nginx # 后面可使用 %{version} 引用 Version: %{base_version} # 标明第几次打包,后面可使用 %{release} 引用 Release: %{base_release} # 打包组织或者人员 Vendor: Nginx, Inc. Group: System Environment/Daemons # 软件分组,具体类别有: Amusements/Games (娱乐/游戏) Amusements/Graphics(娱乐/图形) Applications/Archiving (应用/文档) Applications/Communications(应用/通讯) Applications/Databases (应用/数据库) Applications/Editors (应用/编辑器) Applications/Emulators (应用/仿真器) Applications/Engineering (应用/工程) Applications/File (应用/文件) Applications/Internet (应用/因特网) Applications/Multimedia(应用/多媒体) Applications/Productivity (应用/产品) Applications/Publishing(应用/印刷) Applications/System(应用/系统) Applications/Text (应用/文本) Development/Debuggers (开发/调试器) Development/Languages (开发/语言) Development/Libraries (开发/函数库) Development/System (开发/系统) Development/Tools (开发/工具) Documentation (文档) System Environment/Base(系统环境/基础) System Environment/Daemons (系统环境/守护) System Environment/Kernel (系统环境/内核) System Environment/Libraries (系统环境/函数库) System Environment/Shells (系统环境/接口) User Interface/Desktops(用户界面/桌面) User Interface/X (用户界面/X窗口) User Interface/X Hardware Support (用户界面/X硬件支持) Packager: xxx@xxx.com # 打包的人 License: GPLv2 # 软件授权方式,通常是GPL(自由软件)或GPLv2、BSD URL: https://nginx.org/ # 指编译的目标处理器架构,noarch 标识不指定,但通常都是以 /usr/lib/rpm/marcros 中的内容为默认值 BuildArch: x86_64 Prefix: %{_prefix} //这个主要是为了解决今后安装rpm包时,并不一定把软件安装到rpm中打包的目录的情况。 # 这样,必须在这里定义该标识,并在编写 %install 脚本的时候引用,才能实现 rpm 安装时重新指定位置的功能 # 一般是设置为 %_topdir/BUILDROOT 不建议声明,除非你有子目录需求。后面可使用 $RPM_BUILD_ROOT 方式引用 # 测试了下,好像没啥用,可能废弃了? BuildRoot: %{_tmppath}/%{name}-%{base_version}-%{base_release}-root # 单行或者多行,也就是你 rpmbuild 的时候提醒需要啥包 BuildRequires: gcc,make BuildRequires: zlib-devel,pcre-devel # 版本号要求的话,符号左右有空格 BuildRequires: openssl-devel >= 1.0.2 # yum install centos-release-scl -y && yum install devtoolset-8-gcc devtoolset-8-gcc-c++ -y BuildRequires: centos-release-scl BuildRequires: devtoolset-8-gcc,devtoolset-8-gcc-c++ # 安装 rpm 的时候前置依赖 Requires: openssl >= 1.0.2 # 还有例如PreReq、Requires(pre)、Requires(post)、Requires(preun)、Requires(postun)、BuildRequires等都是针对不同阶段的依赖指定。 #Conflicts: xxx # 互斥的包 # 可以带多个用 Source1、Source2 等源,后面也可以用 %{source1}、%{source2} 引用 # 可以使用 URL Source0: https://nginx.org/download/%{name}-%{version}.tar.gz Source1: nginx.conf Source2: nginx.default.conf %description nginx [engine x] is an HTTP and reverse proxy server, as well as a mail proxy server. # 预处理通常用来执行一些解开源程序包的命令,为下一步的编译安装作准备。prep和下面的build,install段一样,除了可以执行RPM所定义的宏命令(以%开头)以外,还可以执行SHELL命令。 # 功能上类似于./configure。用来准备要编译的软件。通常,这一段落将归档中的源代码解压,并应用补丁。 # 这些可以用标准的 shell 命令完成,但是更多地使用预定义的宏。它一般包含 %setup 与 %patch 两个命令。%setup 用于将软件包打开,执行 %patch 可将补丁文件加入解开的源程序中。 %prep %setup -q -T -c -b 0 # %{__cp} %{SOURCE1} %{_builddir}/%{name}-%{version}/%{name}-%{version}/conf/ # 前面定义了宏,使用下面的 # 拷贝自定义的 nginx 文件 #%{__cp} %{SOURCE1} %{bdir}/%{name}-%{version}/conf/ # 默认解压到 %{_builddir}/%{name}-%{version}目录,此处加了-c,保持了源目录。nginx的源码目录为 %{_builddir}/%{name}-%{version}/nginx-1.19.0/ # %setup 指令可以自动提取 tar、zip、gzip、bzip2、pack、compress 和 lzh 压缩文件。不过,tar-gzip 格式使用最广泛。 # http://ftp.rpm.org/max-rpm/s1-rpm-inside-macros.html#S2-RPM-INSIDE-SETUP-MACRO # %setup -q #将 tar 命令的输出关闭。 # %setup -a 切换目录前,解压指定 Source 文件,例如 `-a 0` 表示解压 `Source0` # %setup -n newdir 将软件包解压在newdir目录。 # %setup -c 解压缩之前先产生目录。 如果压缩包里有目录,用了 -c 就两层目录了。如果没目录,则是BUILD/nginx-1.19.0 # %setup -b num 将第 num 个 source 文件解压缩。 # %setup -D 解压前不删除目录 # SOURCE 下面有多个.tar.gz 需要解压的时候需要使用这个 # %setup -T 不使用default的解压缩操作。 # # %setup -T -b 0 将第 0 个源代码文件解压缩。 # %setup -c -n newdir 指定目录名称 newdir,并在此目录产生 rpm 套件。 # 假如 有多个Source 的压缩包,单独解压 Source1,可以下面这样写。%setup -q -b 1 则会解压所有的 # %setup -q -T -b 1 # 但是这样缺少目录,所以加上-c : %setup -q -T -c -b 1 但是多个同时解压因为解压之前会删除目录,所以我们加 -D 选项不删除,也就是下面的多个 # # %{__rm} -rf %{_builddir}/%{name}-%{version} # %setup -q -T -D -c -b 0 # %setup -q -T -D -c -b 1 %build #此阶段会在BUILD目录的, 我们需要cd %{_builddir}/%{name}-%{version} cd %{bdir}/%{name}-%{version} # gcc8 source /opt/rh/devtoolset-8/enable %if %{nginx_debug} ./configure %{BASE_CONFIGURE_ARGS} \ --with-cc-opt="%{WITH_CC_OPT}" \ --with-ld-opt="%{WITH_LD_OPT}" \ --with-debug make %{?_smp_mflags} %{__mv} %{bdir}/objs/nginx \ %{bdir}/objs/nginx-debug %endif ./configure %{BASE_CONFIGURE_ARGS} \ --with-cc-opt="%{WITH_CC_OPT}" \ --with-ld-opt="%{WITH_LD_OPT}" make %{?_smp_mflags} %install %define _build_id_links none #此阶段会在 %{_builddir}目录 BUILD/ cd %{bdir}/%{name}-%{version} [ "$RPM_BUILD_ROOT" != "/" ] && %{__rm} -rf $RPM_BUILD_ROOT %{__make} DESTDIR=$RPM_BUILD_ROOT INSTALLDIRS=vendor install %if %{nginx_debug} %{__install} -m755 %{bdir}/%{name}-%{version}/objs/nginx-debug \ $RPM_BUILD_ROOT%{_sbindir}/nginx-debug %endif %{__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%{_sysconfdir}/nginx/conf.d %{__rm} $RPM_BUILD_ROOT%{_sysconfdir}/nginx/nginx.conf %{__install} -m 644 -p %{SOURCE1} \ $RPM_BUILD_ROOT%{_sysconfdir}/nginx/nginx.conf %{__install} -m 644 -p %{SOURCE2} \ $RPM_BUILD_ROOT%{_sysconfdir}/nginx/conf.d/default.conf #%clean #[ "$RPM_BUILD_ROOT" != "/" ] && %{__rm} -rf "$RPM_BUILD_ROOT" #%{__rm} -rf $RPM_BUILD_DIR/%{name}-%{version} # 任何打包的文件,都需要在这个包的详细的文件列表中 %files # 设定默认权限,(文件权限,用户名,组名,目录权限) %defattr(-,root,root) %{_sbindir}/nginx %if %{nginx_debug} %{_sbindir}/nginx-debug %endif %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 %dir %{_datadir}/nginx/html %{_datadir}/nginx/html/* %attr(0755,root,root) %dir %{_localstatedir}/cache/nginx %attr(0755,root,root) %dir %{_localstatedir}/log/nginx # rpm -q --scripts packagename # 可以看到脚本的信息 # 安装之前,通常用户和目录创建之类的 %pre # 这里的1为安装;0为卸载 if [ $1 == 1 ]; then # 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 fi #安装后的工作,如设置服务的开机启动,定时任务的设定,启动服务等等 %post # Register the nginx service # 这里的1为安装 if [ $1 -eq 1 ]; then # print site info cat <<BANNER ---------------------------------------------------------------------- Thanks for using nginx! Please find the official documentation for nginx here: * https://nginx.org/en/docs/ Please subscribe to nginx-announce mailing list to get the most important news about nginx: * https://nginx.org/en/support.html Commercial subscriptions for nginx are available on: * https://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 # 卸载前执行的脚本,在升级的时候会执行。$1 -eq 0 表示卸载 %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 Apr 13 2021 Andrei Belov <defan@nginx.com> - 1.19.10-1%{?dist}.ngx - 1.19.10-1 * Tue Mar 30 2021 Konstantin Pavlov <thresh@nginx.com> - 1.19.9-1%{?dist}.ngx - 1.19.9-1
注意上面一些变量目录的清理,判断下是不是 /
。如果这样制作出来的 rpm 包有问题,也就是同一个机器上都无法安装,报错 glibc 版本依赖的话。需要在上面添加下面属性,参考困扰一天的rpm打包问题
制作 rpm
1 rpmbuild -bb SPECS/nginx.spec
起个容器进去安装,先安装 openssl 依赖,然后安装:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 $ rpm -ivh nginx-1.19.10-1.el7.ngx.x86_64.rpm Preparing... ################################# [100%] Updating / installing... 1:nginx-1:1.19.10-1.el7.ngx ################################# [100%] ---------------------------------------------------------------------- Thanks for using nginx! Please find the official documentation for nginx here: * https://nginx.org/en/docs/ Please subscribe to nginx-announce mailing list to get the most important news about nginx: * https://nginx.org/en/support.html Commercial subscriptions for nginx are available on: * https://nginx.com/products/ ---------------------------------------------------------------------- # 启动 $ nginx -g 'daemon off;'
容器里 curl 下:
1 2 3 4 5 6 7 8 9 10 $ docker exec -ti d4a curl -I localhost HTTP/1.1 200 OK Server: nginx/1.19.10 Date: Tue, 03 Aug 2021 02:08:51 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Tue, 03 Aug 2021 02:07:29 GMT Connection: keep-alive ETag: "6108a4e1-264" Accept-Ranges: bytes
官方的 SPEC 文件里实际还处理了 systemd 之类的,我这里就不搞了,还有一些宏之类的也不讲解了,基本够用了。
一些后话 nginx 这种依赖 openssl-libs
的,可以把依赖打包到非根目录里进去,然后用变量 LD_LIBRARY_PATH
1 2 3 4 5 6 7 ls -l lib64/ total 2924 lrwxrwxrwx 1 root root 19 Aug 6 11:09 libcrypto.so.10 -> libcrypto.so.1.0.2k -rwxr-xr-x 1 root root 2520768 Aug 6 10:22 libcrypto.so.1.0.2k lrwxrwxrwx 1 root root 16 Aug 6 11:09 libssl.so.10 -> libssl.so.1.0.2k -rwxr-xr-x 1 root root 470376 Aug 6 10:22 libssl.so.1.0.2k
%files 文件带标记和各种情况总结
文件标记
在update包中是否更新
本地磁盘没有被修改
本地磁盘被修改过
无
无论有无更新,反正都是替换
%config
没更新
替换(旧文件删除)
保留修改过的文件,不替换
%config
更新
替换(旧文件删除)
旧文件被保存为 xxx.rpmsave
,新文件替换旧文件
%config(noreplace)
没更新
替换(旧文件删除)
保留修改过的文件,不替换
%config(noreplace)
更新
替换(旧文件删除)
旧文件保持不变,新文件重命名为xxx.rpmnew
当rpm包中该文件的标记方法发生改变的两个场景:
文件标记
在update包中是否更新
本地磁盘被修改过
%config(noreplace)
-> %config
更新
文件被替换,旧文件被保存为xxx.rpmsave
%config
-> %config(noreplace)
更新
旧文件保持不变,update包中的新文件重命名为xxx.rpmnew
常用变量 可以使用 rpm 命令行查看变量的值:
1 2 $ rpm --eval '%{_arch}' x86_64
macro
definition
comment
%{_sysconfdir}
/etc
———-
%{_prefix}
/usr
can be defined to /app
for flatpak builds
%{_exec_prefix}
%{_prefix}
default: /usr
%{_includedir}
%{_prefix}/include
default: /usr/include
%{_bindir}
%{_exec_prefix}/bin
default: /usr/bin
%{_libdir}
%{_exec_prefix}/%{_lib}
default: /usr/%{_lib}
%{_libexecdir}
%{_exec_prefix}/libexec
default: /usr/libexec
%{_sbindir}
%{_exec_prefix}/sbin
default: /usr/sbin
%{_datadir}
%{_datarootdir}
default: /usr/share
%{_infodir}
%{_datarootdir}/info
default: /usr/share/info
%{_mandir}
%{_datarootdir}/man
default: /usr/share/man
%{_docdir}
%{_datadir}/doc
default: /usr/share/doc
%{_rundir}
/run
%{_localstatedir}
/var
%{_sharedstatedir}
/var/lib
%{_lib}
lib64
lib` on 32bit platforms
遇到的问题 1 2 3 4 + /usr/lib/rpm/find-debuginfo.sh --strict-build-id -m --run-dwz --dwz-low-mem-die-limit 10000000 --dwz-max-die-limit 110000000 /test/BUILD/nginx-1.19.10 extracting debug info from /test/BUILDROOT/nginx-1.19.10-1.el7.ngx.x86_64/usr/sbin/nginx Dest dir longer than base dir is not supported error: Bad exit status from /var/tmp/rpm-tmp.NhXfFj (%install)
就是第一行的 %define _topdir %(echo $PWD)
,设置了就有问题,不设置老老实实在 ~/rpmbuild
目录里就没问题。是 debugedit
引起的,这个 说了个解决办法但是没看懂咋搞。
参考