赞
踩
基于CentOS 7系列的软件工程在开发完成之后,总有一个如何发布的问题,通常的选择是以RPM资源包的形式发布,这需要开发者额外开发rpm打包脚本(project.spec),但在实际开发过程中几乎每次新工程代码发布流程总是遇到各种坑,诸多不顺。下面以一个简单脚本的打包流程为例梳理整个打包流程。
[elvis@localhost ~]$ which rpmbuild
/usr/bin/rpmbuild
[elvis@localhost ~]$ rpm -q -f /usr/bin/rpmbuild
rpm-build-4.11.3-17.el7.x86_64
打包需要事先在CentOS中安装相应的rpm-build包。
首先,检查topdir顶层目录配置。其中RPM相关的配置项在/usr/lib/rpm目录下:
[elvis@localhost ~]$ grep -rn _topdir /usr/lib/rpm/*
/usr/lib/rpm/macros:159:%_builddir %{_topdir}/BUILD
/usr/lib/rpm/macros:214:%_rpmdir %{_topdir}/RPMS
/usr/lib/rpm/macros:222:%_sourcedir %{_topdir}/SOURCES
/usr/lib/rpm/macros:226:%_specdir %{_topdir}/SPECS
/usr/lib/rpm/macros:229:%_srcrpmdir %{_topdir}/SRPMS
/usr/lib/rpm/macros:232:%_buildrootdir %{_topdir}/BUILDROOT
/usr/lib/rpm/macros:241:%_topdir %{getenv:HOME}/rpmbuild
其实topdir可以指定到任意目录,这个顶层目录作为之后打包发布的顶层目录,可配置为:
echo '%_topdir %(echo $HOME)/rpmbuild' > ~/.rpmmacros
然后,创建打包目录,采纳默认的顶层目录为/home_dir/rpmbuild,在该顶层目录下面创建如下目录结构:
mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
到此,打包环境准备完成,之后便是经常出错的打包脚本开发阶段。
首先,整个目录结构组织形式如下:
[elvis@localhost rpmbuild]$ tree
.
├── BUILD <--编译目录
│ ├── bridge-daemon.init
│ └── bridge-daemon.spec
├── BUILDROOT <--临时安装目录,rpmbuild打包该目录生成RPM资源包
├── RPMS <--生成的RPM资源包存放路径
│ └── x86_64
│ └── bridge-daemon-0.0.1-el7.x86_64.rpm
├── SOURCES <--源码目录
├── SPECS <--打包脚本默认路径(可按需存放到其他路径)
└── SRPMS <--SourceRPM包路径,用于发布源代码
7 directories, 3 files
其中System V初始化脚本如下所示,同时满足:
将bridge-daemon设置成开机自启服务
通过System V管理bridge-daemon的整个生命周期
[elvis@localhost BUILD]$ cat bridge-daemon.init #!/bin/bash export LANG=C . /etc/init.d/functions umask 133 start() { action "Prepare bridge-daemon: " BR=bridge-daemon if [ -d /sys/class/net/$BR/bridge/. ]; then ifconfig $BR down brctl delbr $BR else brctl addbr $BR ifconfig $BR 192.16.0.1/20 up fi if [ $? != 0 ] ; then exit 1 fi } stop() { action "Stop bridge-daemon bridge!" BR=bridge-daemon if [ -d /sys/class/net/$BR/bridge/. ]; then ifconfig $BR down brctl delbr $BR fi } restart() { stop start } status() { action "Checking bridge-daemon status: " ifconfig | grep bridge-daemon } case "$1" in start) start ;; stop) stop ;; restart) restart ;; status) status ;; *) echo $"Usage: bridge-daemon {start|stop|restart|status}" exit 1 esac exit $?
RPM打包最重要的开发工作便是负责RPM执行动作的SPEC脚本的开发,其有一套自定义的语法规则,特别是一些全局变量的定义,相关配置项在/usr/lib/rpm目录下。SPEC开发过程中遇到非常多的全局%variable定义,正是这些变量导致了几乎每次新发布总会踩到一些坑,并且有些变量在各Linux平台下不通用,各有各的定义。其中常用变量定义如下:
[elvis@localhost BUILD]$ cat bridge-daemon.spec Summary: Prepare net environment #介绍域,包名、版本等信息 Name: bridge-daemon Version: 0.0.1 Release: el7 License: GPL Group: System Environment/Base ExclusiveArch: x86_64 %description bridge-daemon prepare net bridge environment %define __spec_install_pre /bin/true #为了保留BUILDROOT目录下的中间产物 %prep #准备阶段,主要是为后续执行的准备工作 mkdir -p %{buildroot}%{_sysconfdir}/rc.d/init.d install -c -m 755 $OLDPWD/bridge-daemon.init %{buildroot}%{_sysconfdir}/rc.d/init.d/bridge-daemon exit 0 %build #编译阶段,比如编译C工程的configure,make等操作 %install #安装阶段 %clean #一个良好的习惯就是清理临时安装目录 rm -rf %{buildroot} %files #待安装文件列表 %{_sysconfdir} %post #安装后执行的脚本域 /sbin/chkconfig --add bridge-daemon /sbin/chkconfig bridge-daemon on echo "running post scriplet" /sbin/service bridge-daemon start %pre #安装前执行的脚本域 if [ $1 -eq 2 ]; then /sbin/service bridge-daemon stop >/dev/null 2>&1 fi %preun #卸载前(pre-uninstall)执行的脚本域 if [ $1 -eq 0 ]; then /sbin/service bridge-daemon stop fi %changelog * Tue Jun 27 2017 Elvis Huang <sduhuangshuai@gmail.com> - Initial rpm packaging for bridge-daemon
最后执行动作生成RPM资源包:
[elvis@localhost BUILD]$ rpmbuild -bb bridge-daemon.spec
检查资源包内容:
[elvis@localhost x86_64]$ rpm -qpl bridge-daemon-0.0.1-el7.x86_64.rpm
/etc
/etc/rc.d
/etc/rc.d/init.d
/etc/rc.d/init.d/bridge-daemon
至此,RPM打包流程介绍完毕。之后便是熟悉的通过RPM发布的资源安装管理
[elvis@localhost x86_64]$ sudo rpm -ivh bridge-daemon-0.0.1-el7.x86_64.rpm Preparing... ################################# [100%] Updating /installing... 1:bridge-daemon-0.0.1-el7 #############[100%] running post scriplet Starting bridge-daemon (via systemctl): [ OK ] [elvis@localhost x86_64]$ ifconfig bridge-daemon: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.16.0.1 netmask 255.255.240.0 broadcast 192.16.15.255 inet6 fe80::54e1:bcff:fecf:c701 prefixlen 64 scopeid 0x20<link> ether 56:e1:bc:cf:c7:01 txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 27 bytes 3924 (3.8 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 0 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。