⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 cnblogs.com/wangrudong003/p/10502043.html 「神牛003」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

本篇和大家分享的是Spring Boot打包并结合Shell部署部署,重点分享一个shell程序启动工具,希望脚本能方便工作;

  • profile 指定不同环境的配置
  • maven-assembly-plugin打发布压缩包
  • 分享shenniu_publish.sh程序启动工具
  • linux上使用shenniu_publish.sh启动程序

profile 指定不同环境的配置

通常将程序设置成一个个部署环境:开发我们对这些环境的配置,测试,在线等,可以通过方式:

  • 通过application.yml中编码指定profile.active=uat的方式指定
  • 通过mvn中的profiles来不同环境的配置文件夹,人工可以在手动构思一个生成不同环境的包(推荐)

这里我们要讲的是第三个配置,首先在mvn中如下内容:

<profiles>
<profile>
<id>node</id>
<properties>
<!--传递给脚本的参数值-->
<activeProfile>node</activeProfile>
<package-name>${scripts_packageName}</package-name>
<boot-main>${scripts_bootMain}</boot-main>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>node1</id>
<properties>
<activeProfile>node1</activeProfile>
<package-name>${scripts_packageName}</package-name>
<boot-main>${scripts_bootMain}</boot-main>
</properties>
</profile>
<profile>
<id>node2</id>
<properties>
<activeProfile>node2</activeProfile>
<package-name>${scripts_packageName}</package-name>
<boot-main>${scripts_bootMain}</boot-main>
</properties>
</profile>
</profiles>

节点粗解:

id:使用指定不同环境配置文件所在的目录,如下我这里:

properties:该像中的节点是可以作为参数传递给其他配置文件的,比如我这里的节点名称就可以在另外的package-name xml或者shell文件中通过${package-name}获取到, :

activeByDefault:指定默认环境配置文件夹

maven-assembly-plugin打发布压缩包

springboot程序包,可以分为jar包和war包;有情况是我们配置这些文件,或者这些文件是依赖打包的,然后把这里压缩成一个zip包,方便上传到linux;此时通过maven-assembly-plugin和maven-jar-plugin就可以做到,mvn的配置如:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>${scripts_bootMain}</mainClass>
</manifest>
</archive>
<!--打包排除项-->
<excludes>
<exclude>**/*.yml</exclude>
<exclude>**/*.properties</exclude>
<exclude>**/*.xml</exclude>
<exclude>**/*.sh</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>make-a-jar</id>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<!-- The configuration of the plugin -->
<configuration>
<!-- Specifies the configuration file of the assembly plugin -->
<descriptors>
<descriptor>${project.basedir}/src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>

地方如下:

  • mainClass节点:使用指定启动main函数入口类的路径,如这里的:com.sm.EurekaServerApplication
  • 排除节点:放置中配置等一些列后缀包文件,因为我们这些配置文件把主包放在主包中
  • 描述符节点:使用指定程序集插件的assembly.xml配置文件

上面的mvn配置,我们还需要assembly.xml的配置,这里有提取结合了shell脚本程序的配置:

<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd
http://maven.apache.org/ASSEMBLY/2.0.0 ">
<id>${activeProfile}</id>
<!--打包成一个用于发布的zip文件-->
<formats>
<format>zip</format>
</formats>
<!--true:zip中生成一级目录(此处屏蔽,配合脚本需要profiles后缀)-->
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<!--打包进zip文件的lib目录-->
<useProjectArtifact>false</useProjectArtifact>
<outputDirectory>${package-name}-${activeProfile}/lib</outputDirectory>
<unpack>false</unpack>
</dependencySet>
</dependencySets>

<fileSets>
<!-- 配置文件打包进zip文件的conf目录 -->
<fileSet>
<directory>${project.basedir}/src/main/profiles/${activeProfile}</directory>
<outputDirectory>${package-name}-${activeProfile}/conf</outputDirectory>
<includes>
<include>**/*</include>
<!--<include>*.xml</include>-->
<!--<include>*.properties</include>-->
<!--<include>*.yml</include>-->
</includes>
</fileSet>

<!--启动脚本打包进zip文件-->
<fileSet>
<directory>${project.basedir}/src/main/scripts</directory>
<outputDirectory></outputDirectory>
<includes>
<include>**/*</include>
</includes>
<!-- 文件文件权限为777 -->
<fileMode>777</fileMode>
<!-- 目录权限为777 -->
<directoryMode>777</directoryMode>
<!--脚本中参数变量为pom中的值 关键-->
<filtered>true</filtered>
</fileSet>

<!-- 项目编译出来的jar打包进zip文件 -->
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>${package-name}-${activeProfile}/</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>

重点介绍:

  • 格式差:把配置文件和jar包等压缩成什么文件格式,这里可以有:zip,tar等
  • fileMode:指定scripts目录下脚本文件(这里是:shenniu_publish.sh)在linux上文件权限为777
  • 过滤节点:脚本中的参数参数为pom的profiles中properties的值(该配置,是把mvn中的值映射生成到sh文件中,如:${package-name})

完成整个配置后,此时我们可以通过构思切换不同的环境来打zip包,如下图:

分享shenniu_publish.sh程序启动工具

上面步骤完成了zip格式的发布包,我们再分享下启动程序的shell脚本,该脚本具有的功能如:

  • 解压zip+启动jar包
  • 启动jar包
  • 停止运行
  • 重启jar程序

现在该shell中封装了一个启动jar命令的方式:

  • java -cp
  • java -jar

定制命令格式:

查看全部的shell代码:

#!/usr/bin/env bash
#可变参数变量
languageType="javac" #支持 java,javac,netcore 发布
#参数值由pom文件传递
baseZipName="${package-name}-${activeProfile}" #压缩包名称 publish-test.zip的publish
packageName="${package-name}" #命令启动包名 xx.jar的xx
mainclass="${boot-main}" #java -cp启动时,指定main入口类;命令:java -cp conf;lib\*.jar;${packageName}.jar ${mainclass}

#例子
# baseZipName="publish-test" #压缩包名称 publish-test.zip的publish
# packageName="publish" #命令启动包名 publish.jar的xx

#固定变量
basePath=$(cd `dirname $0`/; pwd)
baseZipPath="${basePath}/${baseZipName}.zip" #压缩包路径
baseDirPath="${basePath}" #解压部署磁盘路径
pid= #进程pid

#解压
function shenniu_unzip()
{
echo "解压---------------------------------------------"
echo "压缩包路径:${baseZipPath}"
if [ ! `find ${baseZipPath}` ]
then
echo "不存在压缩包:${baseZipPath}"
else
echo "解压磁盘路径:${baseDirPath}/${baseZipName}"
echo "开始解压..."

#解压命令
unzip -od ${baseDirPath}/${baseZipName} ${baseZipPath}

#设置执行权限
chmod +x ${baseDirPath}/${baseZipName}/${packageName}

echo "解压完成。"
fi
}

#检测pid
function getPid()
{
echo "检测状态---------------------------------------------"
pid=`ps -ef | grep -n ${packageName} | grep -v grep | awk '{print $2}'`
if [ ${pid} ]
then
echo "运行pid:${pid}"
else
echo "未运行"
fi
}

#启动程序
function start()
{
#启动前,先停止之前的
stop
if [ ${pid} ]
then
echo "停止程序失败,无法启动"
else
echo "启动程序---------------------------------------------"

#选择语言类型
read -p "输入程序类型(java,javac,netcore),下一步按回车键(默认:${languageType}):" read_languageType
if [ ${read_languageType} ]
then
languageType=${read_languageType}
fi
echo "选择程序类型:${languageType}"

#进入运行包目录
cd ${baseDirPath}/${baseZipName}

#分类启动
if [ "${languageType}" == "javac" ]
then
if [ ${mainclass} ]
then
nohup java -cp conf:lib\*.jar:${packageName}.jar ${mainclass} >${baseDirPath}/${packageName}.out 2>&1 &
#nohup java -cp conf:lib\*.jar:${packageName}.jar ${mainclass} >/dev/null 2>&1 &
fi
elif [ "${languageType}" == "java" ]
then
nohup java -jar ${baseDirPath}/${baseZipName}/${packageName}.jar >/dev/null 2>&1 &
# java -jar ${baseDirPath}/${baseZipName}/${packageName}.jar
elif [ "${languageType}" == "netcore" ]
then
#nohup dotnet run ${baseDirPath}/${baseZipName}/${packageName} >/dev/null 2>&1 &
nohup ${baseDirPath}/${baseZipName}/${packageName} >/dev/null 2>&1 &
fi

#查询是否有启动进程
getPid
if [ ${pid} ]
then
echo "已启动"
#nohup日志
tail -n 50 -f ${baseDirPath}/${packageName}.out
else
echo "启动失败"
fi
fi
}

#停止程序
function stop()
{
getPid
if [ ${pid} ]
then
echo "停止程序---------------------------------------------"
kill -9 ${pid}

getPid
if [ ${pid} ]
then
#stop
echo "停止失败"
else
echo "停止成功"
fi
fi
}

#启动时带参数,根据参数执行
if [ ${#} -ge 1 ]
then
case ${1} in
"start")
start
;;
"restart")
start
;;
"stop")
stop
;;
"unzip")
#执行解压
shenniu_unzip
#执行启动
start
;;
*)
echo "${1}无任何操作"
;;
esac
else
echo "
command如下命令:
unzip:解压并启动
start:启动
stop:停止进程
restart:重启

示例命令如:./shenniu_publish start
"
fi

上面小节说的,中的参数 package-,activeProfile,boot-main 中的都是 mvn 中的profilesproperties,正如其名的参数,脚本代码提供了需要人工去修改,只需要改变就是mvn的参数包可以;其实在我们生成zip的时候,shell中的参数就被替换了,可以看zip中的shell文件内容如:

把生成的zip上传到linux上,通过命令解压:

1 解压-od eureka-server-0.0.1-node eureka-server-0.0.1-node.zip

这个shell脚本中包含有有,但是我在打包的时候通过了zip中,所以可以通过手动调整解压了目录,此时就可以进入解析目录,例如:

注:这里第一次脚本./shenniu_publishsh脚本的时候,提示了错误信息;是因为我是在windows上编辑的这个脚本,其空格等和linux上不一样,所以会有运行问题,要解决可以使用vim在linux把文件转成linux格式,命令:

1 vim shenniu_publish.sh 
2 设置 ff=unix
3 :wq

执行完之后,再来运行脚本./shenniu_publish.sh,此时有如下提示:

此时文件是解压状态,因此只需要启动命令启动程序即可:

这里sniu_publish.sh脚本使用就完成了,只要脚本没有提示错误,到基本启动和启动henjar服务;其他restart就可以执行这样的命令了:

可以去代码,希望这个项目可以研究下shell给你带来高效和用好的学习思路,下面是测试示例git地址,脚本在eureka-server中:

https://github.com/shenniubuxing3/springcloud-Finchley.SR2

文章目录
  1. 1. profile 指定不同环境的配置
  2. 2. maven-assembly-plugin打发布压缩包
  3. 3. 分享shenniu_publish.sh程序启动工具