Backend Development 15 min read

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.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Spring Boot Packaging with Maven Assembly Plugin and shenniu_publish.sh Deployment Script

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"
fi

To 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 .

BackendautomationdeploymentMavenSpring Bootshell script
Code Ape Tech Column
Written by

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

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.