Maven打包成RPM RPM全称是 Red Hat Package Manager(Red Hat包管理器)。几乎所有的 Linux 发行版本都使用这种形式的软件包管理安装、更新和卸载软件。
在devops链条上,常见的部署方式是通过持续集成工具如jenkins/CI 构建和发布jar包到服务端制定目录。不过随着越来越多的应用趋向于paas 平台,本地化自动部署的需求越来越多,在软件包的安装过程中各种自动控制命令的集成也越来越复杂,jenkins等部署方式已经无法满足需求,这时候将软件包和集成脚本一起打包成rpm包的形式,也是一种另外的思路。对于最终用户来说,使用 RPM所提供的功能来维护系统是比较容易和轻松的。安装、卸载和升级RPM软件包只需一条命令就能搞定。
利用rpm-maven-plugin插件实现rpm构建,以便于RPM软件仓库管理。
基本单项目 打包成rpm 
多module 项目打包成rpm 
纯前端项目 打包成rpm 
rpm script 应用-通过自动创建软连接实现rpm包自动升级 
 
备注:
rpm-maven-plugin 需要在linux 机器上才能正常运行,运行机器需要
一、基础项目打包 pom文件配置
工程信息,声明rpm包要用到的相关信息,例如project.version、rpm.release、rpm.basedir等等
pom.xml 1 2 3 4 5 6 7 8 9 10 11 <modelVersion > 4.0.0</modelVersion > <groupId > io.github.ifengkou</groupId > <artifactId > web-api</artifactId > <version > 0.0.1-SNAPSHOT</version > <properties > 	...... 	<rpm.release > 0.3.0</rpm.release >  	<rpm.owner > isuhadoop</rpm.owner >  	<rpm.basedir > /data/micro-services/9090-web-api-jar</rpm.basedir >  </properties > 
pom文件中加入plugin,执行 maven clean package 可以直接打包
pom.xml 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 <plugin >     <groupId > org.codehaus.mojo</groupId >      <artifactId > rpm-maven-plugin</artifactId >      <version > 2.1.5</version >      <extensions > true</extensions >      <executions >          <execution >              <goals >                  <goal > rpm</goal >              </goals >          </execution >      </executions >      <configuration >          <prefix > {install_dir}</prefix >          <copyright > GPL (c) 2005, SWWDC</copyright >          <distribution > loganshen</distribution >          <group > ifengkou.github.io</group >          <packager > loganshen</packager >      	 <prefix > ${rpm.basedir}</prefix >  		 <name > web-api</name >  		 <version > ${project.version}</version >  		 <autoProvides > false</autoProvides >  		 <autoRequires > false</autoRequires >  		 <needarch > noarch</needarch >  		 <targetOS > linux</targetOS >  		 <release > ${rpm.release}</release >          <requires >              <require > java-1.7.0 >= 1.7</require >          </requires >          <mappings >              <mapping >                  <directory > ${install_dir}/jars</directory >                  <username > tomcat</username >                  <groupname > tomcat</groupname >                  <sources >                      <source >                          <location > target/${project.artifactId}-${project.version}</location >                      </source >                  </sources >              </mapping >              <mapping >                  <directory > ${install_dir}/bin</directory >                  <filemode > 755</filemode >                  <username > tomcat</username >                  <groupname > tomcat</groupname >                  <sources >                      <source >                          <location > ${basedir}/scripts</location >                      </source >                  </sources >              </mapping >          </mappings >      </configuration >  </plugin > 
二、多module 打rpm包 加了rpm包插件后,为了在构建时,不影响日常研发测试,所以在打包的rpm插件配置中,不能将其放入maven 的lifecycle
日常构建,打jar包:
发布rpm包:
1 mvn clean package rpm:attached-rpm -U 
父项目(配置空rpm)
父项目需要配置 空的rpm配置,其他所有子module 都需要配置,否则就会报错。
其中<phase>none</phase> 表示:unbinds rpm creation from maven lifecycle。这样在构建时,只有在显示指定 rpm:attached-rpm时,才会主动构建rpm包,否则不会触发。
其中 <directory>/tmp</directory> 并不存在,所以不会打包任何东西到rpm中
pom.xml 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 <plugin >   <groupId > org.codehaus.mojo</groupId >    <artifactId > rpm-maven-plugin</artifactId >    <version > 2.1.5</version >    <inherited > false</inherited >    <executions >      <execution >               <phase > none</phase >        <goals >          <goal > attached-rpm</goal >        </goals >      </execution >    </executions >    <configuration >      <release > 1</release >    	<copyright > GPL (c) 2005, SWWDC</copyright >    	<distribution > loganshen</distribution >    	<group > ifengkou.github.io</group >    	<packager > loganshen</packager >      <prefix > /opt/soft</prefix >      <mappings >        <mapping >          <directory > /tmp</directory >        </mapping >      </mappings >    </configuration >  </plugin > 
controller 项目是可执行jar包最终打包文件,这个与其他module 不一样
pom.xml 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 <plugin >         <groupId > org.codehaus.mojo</groupId >          <artifactId > rpm-maven-plugin</artifactId >          <version > 2.1.5</version >          <executions >            <execution >              <id > generate-rpm</id >              <phase > none</phase >              <goals >                <goal > attached-rpm</goal >              </goals >            </execution >          </executions >          <configuration >            <license > GPL (c) 2005, SWWDC</license >            <distribution > loganshen</distribution >          	<group > ifengkou.github.io</group >          	<packager > loganshen</packager >            <name > rpm-package-name</name >            <prefix > ${rpm.basedir}</prefix >  		   <version > ${project.version}</version >  		   <autoProvides > false</autoProvides >  		   <autoRequires > false</autoRequires >  		   <needarch > noarch</needarch >  		   <targetOS > linux</targetOS >  		   <release > ${rpm.release}</release >            <defineStatements >              <defineStatement > _unpackaged_files_terminate_build 0</defineStatement >            </defineStatements >            <mapping >                <directory > ${rpm.basedir}/${rpm.release}/jars</directory >                <sources >                  <source >                    <location > ${basedir}/target/web-api.jar</location >                  </source >                </sources >              </mapping >              <mapping >                <directory > ${rpm.basedir}/${rpm.release}/bin</directory >                <sources >                  <source >                    <location > ${basedir}/../builder/scripts</location >                  </source >                </sources >              </mapping >             </mappings >          </configuration >        </plugin >  
三、前端项目打包 前后端分离,前端使用npm run build 构建,生产dist 静态文件,需要在构建时执行shell脚本进行项目构建。构建后需要将生产的目标文件夹倒入到rpm包中
这里用到两个maven plugin:exec-maven-plugin 和 rpm-maven-plugin
先利用exec-maven-plugin 执行shell脚本对工程进行打包生成静态文件,再利用 rpm-maven-plugin 进行rpm打包
日常构建可以通过 mvn clean install 进行构建(需要跳过测试):
1 mvn clean install -Dmaven.test.skip=true  
rpm打包可以通过:
1 mvn clean install rpm:attached-rpm  -Dmaven.test.skip=true  -U 
pom.xml
pom.xml 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 <project  xmlns ="http://maven.apache.org/POM/4.0.0"  xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"  	xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >     <modelVersion > 4.0.0</modelVersion >      <groupId > io.github.ifengkou</groupId >  	<artifactId > front-web</artifactId >  	<version > 1.0</version >  	<properties >  		<project.build.sourceEncoding > UTF-8</project.build.sourceEncoding >  		<rpm.release > 2.9.4</rpm.release >  		<rpm.basedir > /data/micro-services/front-web</rpm.basedir >  	</properties >  	<pluginRepositories >  		<pluginRepository >  			<id > central</id >  			<url > http://maven.aliyun.com/nexus/content/groups/public/</url >  		</pluginRepository >      </pluginRepositories >  	<repositories >  		<repository >  			 			<id > central</id >  			<name > alimaven</name >  			<url > http://maven.aliyun.com/nexus/content/groups/public/</url >  			<layout > default</layout >  			<releases >  				<enabled > true</enabled >  			</releases >  			<snapshots >  				<enabled > true</enabled >  			</snapshots >  		</repository >  	</repositories >      <build >          <plugins >              <plugin >  				<groupId > org.codehaus.mojo</groupId >                  <artifactId > exec-maven-plugin</artifactId >                  <version > 1.5.0</version >                  <executions >                      <execution >                          <id > npm_build</id >                          <phase > install</phase >                          <goals >                              <goal > exec</goal >                          </goals >                          <configuration >                              <executable > ${basedir}/npmbuild.sh</executable >                          </configuration >                      </execution >                  </executions >              </plugin >              <plugin >  				<groupId > org.codehaus.mojo</groupId >  				<artifactId > rpm-maven-plugin</artifactId >  				<version > 2.1.5</version >  				<executions >  					<execution >  						<id > generate-rpm</id >  						<phase > none</phase >  						<goals >  							<goal > attached-rpm</goal >  						</goals >  					</execution >  				</executions >  				<configuration >  					<license > GPL (c) 2005, SWWDC</license >  		          <distribution > loganshen</distribution >  		        	<group > ifengkou.github.io</group >  		        	<packager > loganshen</packager >  					<prefix > ${rpm.basedir}</prefix > 					<name > front-web</name >  					<version > ${project.version}</version >  					<autoProvides > false</autoProvides >  					<autoRequires > false</autoRequires >  					<needarch > noarch</needarch >  					<targetOS > linux</targetOS >  					<release > ${rpm.release}</release > 					<defineStatements >  						<defineStatement > _unpackaged_files_terminate_build 0</defineStatement >  					</defineStatements >  					<mappings >  						<mapping >  							<directory > ${rpm.basedir}/${rpm.release}</directory >  							<username > tomcat</username >  	                    	<groupname > tomcat</groupname >  							<sources >  								<source >  									<location > ${basedir}/dist</location >  								</source >  							</sources >  						</mapping >  					</mappings >  					<postinstallScriptlet >  						<script >  							ln -s ${rpm.basedir}/${rpm.release}/server ${rpm.basedir}/server; 							chown -R isuhadoop:isuhadoop ${rpm.basedir}; 						</script >  					</postinstallScriptlet >  					<postremoveScriptlet >  						<script >  							echo "remove symbolic link " ; 							rm -rf ${rpm.basedir}/server; 							echo "uninstall success" ; 						</script >  					</postremoveScriptlet >  				</configuration >  			</plugin >          </plugins >      </build >  </project > 
npmbuild.sh为前端工程 build 命令,最终在当前目录生成 dist 的静态文件夹
1 2 3 4 5 # !/bin/sh echo "start npm install......" npm install echo "start npm run build ......" npm run build 
生成 dist 的静态文件夹后,只需要通过rpm plugin 的mapping 将该目录打包到rpm的指定目录,后续可以通过nginx 代理到该目录的index.html
四、rpm script 应用-通过自动创建软连接实现rpm包自动升级 例如web-api服务,通过rpm安装之后的路径是/opt/soft/web-api-1.0。然后rpm那能自动创建一个软链接/opt/soft/web-api连接到/opt/soft/web-api-1.0.0,之后如果要升级到web-api-1.1只需要通过rpm包安装web-api-1.1,rpm包自动将/opt/soft/web-api连接到web-api-1.1上。
rpm-plugin 配置
pom.xml 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 <plugin > 	<groupId > org.codehaus.mojo</groupId >  	<artifactId > rpm-maven-plugin</artifactId >  	<version > 2.1.5</version >  	<executions >  		<execution >  			<id > generate-rpm</id >  			<phase > none</phase >  			<goals >  				<goal > attached-rpm</goal >  			</goals >  		</execution >  	</executions >  	<configuration >  		<license > GPL (c) 2005, SWWDC</license >         <distribution > loganshen</distribution >       	<group > ifengkou.github.io</group >       	<packager > loganshen</packager >  		<prefix > ${rpm.basedir}</prefix >  		<name > web-api</name >  		<version > ${project.version}</version >  		<autoProvides > false</autoProvides >  		<autoRequires > false</autoRequires >  		<needarch > noarch</needarch >  		<targetOS > linux</targetOS >  		<release > ${rpm.release}</release >  		<defineStatements >  			<defineStatement > _unpackaged_files_terminate_build 0</defineStatement >  		</defineStatements >  		<mappings >  			<mapping >  				<directory > ${rpm.basedir}/${rpm.release}/jars</directory >  				<sources >  					<source >  						<location > ${basedir}/target/${project.artifactId}-${project.version}.jar</location >  					</source >  				</sources >  			</mapping >  			<mapping >  				<directory > ${rpm.basedir}/${rpm.release}/bin</directory >  				<sources >  					<source >  						<location > ${basedir}/scripts</location >  					</source >  				</sources >  			</mapping >  		</mappings >  		<preinstallScriptlet >  			<scriptFile > install/preinstall.sh</scriptFile >  			<fileEncoding > utf-8</fileEncoding >  		</preinstallScriptlet >  		<postinstallScriptlet >  			<script >  				ln -s ${rpm.basedir}/${rpm.release}/bin ${rpm.basedir}/bin; 				ln -s ${rpm.basedir}/${rpm.release}/jars ${rpm.basedir}/jars; 				chown -R ${rpm.owner}:${rpm.owner} ${rpm.basedir}; 			</script >  		</postinstallScriptlet >  		<preremoveScriptlet >  			<scriptFile > install/preremove.sh</scriptFile >  			<fileEncoding > utf-8</fileEncoding >  		</preremoveScriptlet >  		<postremoveScriptlet >  			<scriptFile > install/postremove.sh</scriptFile >  			<fileEncoding > utf-8</fileEncoding >  		</postremoveScriptlet >  	</configuration >  </plugin > 
有用到了 scriptFile 和 scrpit,scriptFile 没找到怎么传参数,像${rpm.basedir}之类的没法传进去;script 不适合写复杂的shell。还有一种方式是<script>sh ${rpm.basedir}/shell/xxx.sh ${param1} ${param2} </script>,不过要提前将脚本通过mapping复制到${rpm.basedir}/shell,所以只能在postinstall 后用
install/preinstall.sh 主要是为了初始化用户之类的,比如允许web-api 需要特定的用户,那么可以在这个脚本中检测,如果不存在这个用户则创建install/preremove.sh 主要是为了在卸载rpm 时,检测该安装服务是否在运行,如果在运行,则通过命令先shutdownpostinstallScriptlet 主要是为了在安装完成后,创建软连接、对目录或者文件进行chown/chmod,或者是创建service ,自启动等等,根据需求来install/postremove.sh 主要是为了在卸载完成后,主动去删除 安装完成后创建的软连接 
以下脚本仅做参考:
preinstall.sh
preinstall.sh 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 echo "hi,preinstall" ROOT="/data/micro-services/9090-web-api" echo ${ROOT} id isuhadoop have_user=$? if [ ${have_user} -ne 0 ];then     echo "add isuhadoop user" 	useradd isuhadoop fi if [ -d ${ROOT} ];then 	echo "${ROOT} is existed" else     echo "mkdir -p ${ROOT}" 	mkdir -p ${ROOT} 	chmod 777 ${ROOT} fi 
postinstall.sh
postinstall.sh 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # !/bin/bash echo "hi,pre uninstall" ROOT="/data/micro-services/9090-web-api" set +e if test -f ${ROOT}/bin/lryhis.pid ; then     if test -f ${ROOT}/bin/shutdown.sh ;then         echo "try to shutdown the service: sh bin/shutdown.sh"         sh ${ROOT}/bin/shutdown.sh         kill_state=$?         if [ ${kill_state} -ne 0 ];then             echo "shutdown failed"         fi     fi fi set -e 
postremove.sh
postremove.sh 1 2 3 4 5 6 #!/bin/bash echo  "hi,after uninstall,remove base dir & symbolic link" ROOT="/data/micro-services/9090-web-api"  echo  "remove symbolic link " rm -rf ${ROOT} /bin ${ROOT} /jars echo  "uninstall success" 
参考 https://www.mojohaus.org/rpm-maven-plugin/adv-params.html 
https://www.mojohaus.org/exec-maven-plugin/