Spring Boot Packaging with Maven Assembly Plugin and shenniu_publish.sh Deployment Script
This article explains how to use Maven profiles and the Maven Assembly Plugin to create environment‑specific Spring Boot zip packages and provides a reusable shell script (shenniu_publish.sh) for extracting, starting, stopping, and restarting the packaged JAR on Linux, improving deployment efficiency.
Hello everyone, I'm Chen. In this article I share how to package a Spring Boot application and deploy it with a shell script tool, focusing on a reusable shell program to simplify work.
Profiles for Different Environments
Typically a program has multiple deployment environments such as development, test, UAT, and production. You can distinguish configuration files either by setting profile.active=uat in application.yml or, more conveniently, by defining Maven profiles that map to different configuration directories. The article uses the second method.
<profiles>
<profile>
<id>node</id>
<properties>
<!-- parameters passed to the script -->
<activeProfile>node</activeProfile>
<package-name>${scripts_packageName}</package-name>
<boot-main>${scripts_bootMain}</boot-main>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
... (additional profiles node1, node2) ...
</profiles>The id node specifies the directory that contains the environment‑specific configuration files. The properties node defines values (e.g., ${package-name}) that can be referenced in other configuration files or scripts. activeByDefault selects the default profile.
Creating a Release Zip with Maven Assembly Plugin
For a Spring Boot JAR you may want to keep configuration files and third‑party dependencies outside the JAR and package them into a zip for easy upload to Linux. This is achieved with maven-assembly-plugin together with maven-jar-plugin:
<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>
<configuration>
<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>Key points:
mainClass : the entry point of the Java application (e.g., com.sm.EurekaServerApplication).
excludes : removes configuration files from the main JAR so they can be packaged separately.
descriptor : points to the assembly.xml that defines the zip structure.
assembly.xml Configuration
<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">
<id>${activeProfile}</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<useProjectArtifact>false</useProjectArtifact>
<outputDirectory>${package-name}-${activeProfile}/lib</outputDirectory>
<unpack>false</unpack>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>${project.basedir}/src/main/profiles/${activeProfile}</directory>
<outputDirectory>${package-name}-${activeProfile}/conf</outputDirectory>
<includes>
<include>**/*</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.basedir}/src/main/scripts</directory>
<outputDirectory></outputDirectory>
<includes>
<include>**/*</include>
</includes>
<fileMode>777</fileMode>
<directoryMode>777</directoryMode>
<filtered>true</filtered>
</fileSet>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>${package-name}-${activeProfile}/</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>Important nodes:
formats : defines the archive type (zip, tar, etc.).
fileMode : sets executable permission (777) for scripts such as shenniu_publish.sh on Linux.
filtered : enables Maven property substitution inside the script (e.g., ${package-name}).
After configuring Maven, you can select the desired profile in IntelliJ IDEA and generate the zip package.
shenniu_publish.sh – Shell Deployment Tool
The script provides functions to unzip the package, detect the running PID, start, stop, and restart the Java service, and handle command‑line arguments.
#!/usr/bin/env bash
# Variable parameters
languageType="javac" # support java, javac, netcore
baseZipName="${package-name}-${activeProfile}" # zip name
packageName="${package-name}" # jar name without .jar
mainclass="${boot-main}" # main class for java -cp
basePath=$(cd `dirname $0`/; pwd)
baseZipPath="${basePath}/${baseZipName}.zip"
baseDirPath="${basePath}"
pid=
function shenniu_unzip() {
echo "Unzipping..."
if [ ! `find ${baseZipPath}` ]; then
echo "Zip not found: ${baseZipPath}"
else
unzip -od ${baseDirPath}/${baseZipName} ${baseZipPath}
chmod +x ${baseDirPath}/${baseZipName}/${packageName}
echo "Unzip completed."
fi
}
function getPid() {
pid=`ps -ef | grep -n ${packageName} | grep -v grep | awk '{print $2}'`
if [ ${pid} ]; then
echo "Running PID: ${pid}"
else
echo "Not running"
fi
}
function start() {
stop
if [ ${pid} ]; then
echo "Failed to stop, cannot start"
else
read -p "Enter program type (java,javac,netcore) [default: ${languageType}]: " read_languageType
if [ ${read_languageType} ]; then
languageType=${read_languageType}
fi
echo "Program type: ${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 &
fi
elif [ "${languageType}" == "java" ]; then
nohup java -jar ${baseDirPath}/${baseZipName}/${packageName}.jar >/dev/null 2>&1 &
elif [ "${languageType}" == "netcore" ]; then
nohup ${baseDirPath}/${baseZipName}/${packageName} >/dev/null 2>&1 &
fi
getPid
if [ ${pid} ]; then
echo "Started"
tail -n 50 -f ${baseDirPath}/${packageName}.out
else
echo "Start failed"
fi
fi
}
function stop() {
getPid
if [ ${pid} ]; then
echo "Stopping..."
kill -9 ${pid}
getPid
if [ ${pid} ]; then
echo "Stop failed"
else
echo "Stop succeeded"
fi
fi
}
if [ ${#} -ge 1 ]; then
case ${1} in
"start") start ;;
"restart") start ;;
"stop") stop ;;
"unzip") shenniu_unzip ; start ;;
*) echo "${1} has no action" ;;
esac
else
echo "Commands: unzip (extract+start), start, stop, restart"
echo "Example: ./shenniu_publish.sh start"
fiTo use the script on Linux, upload the zip, unzip it (or let the script do it), convert the script to Unix line endings with vim ( set ff=unix), and then run ./shenniu_publish.sh start. The script will start the JAR, display logs, and you can stop or restart with the corresponding commands.
The full source code is available at https://github.com/shenniubuxing3/springcloud-Finchley.SR2 .
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
