likes
comments
collection

手把手教你java项目如何使用startup.sh启动

作者站长头像
站长
· 阅读数 13

「这是我参与2022首次更文挑战的第39天,活动详情查看:2022首次更文挑战

本文项目代码gitee地址: gitee.com/wei_rong_xi…

本篇文章,我们来研究下如何将你的项目打包,通过启动脚本,直接启动执行的方式。相信无论是你在使用nacos,使用skywalking等等一系列的组件时,都是通过脚本直接启动的,无需在启动时候,手动敲命令,指定jvm参数等。当然了,我们自己的项目,也想要有这样的效果。对于运维人员来讲,部署时能够提供极大地便利。

一、开始搭建

下面我将详细展示每个步骤,以工程rob-necessities-gateway为例。

1.1 准备package.xml

package.xml是干什么用的呢?

  • 它指定了我们最终打包的格式,通常是zip

  • 将项目必要文件打包进zip包中。

    • readme.md等等的说明性文件
    • *.bat、 *.sh 等启动脚本
    • jar包

完整的package.xml如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<assembly
        xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">

    <id>bin</id>

    <!-- 最终打包成一个用于发布的zip文件 -->
    <formats>
        <format>zip</format>
    </formats>

    <fileSets>
        <!-- 把项目相关的说明文件,打包进zip文件的根目录 -->
        <fileSet>
            <directory>${project.basedir}</directory>
            <outputDirectory>${file.separator}</outputDirectory>
            <includes>
                <include>README*</include>
                <include>CHANGELOG*</include>
                <include>LICENSE*</include>
                <include>NOTICE*</include>
            </includes>
        </fileSet>

        <!-- 把项目目录中的windows环境启动脚本文件,打包进zip文件的根目录 -->
        <fileSet>
            <directory>./src/main/resources/package</directory>
            <outputDirectory>${file.separator}</outputDirectory>
            <lineEnding>windows</lineEnding>
            <includes>
                <include>*.bat</include>
            </includes>
        </fileSet>

        <!-- 把项目目录中的linux环境启动脚本文件,打包进zip文件的根目录 -->
        <fileSet>
            <directory>./src/main/resources/package</directory>
            <outputDirectory>${file.separator}</outputDirectory>
            <lineEnding>unix</lineEnding>
            <fileMode>0755</fileMode>
            <includes>
                <include>*.sh</include>
            </includes>
        </fileSet>

        <!-- 把项目工程本身的jar文件,打包进zip文件的lib目录 -->
        <fileSet>
            <directory>${project.build.directory}</directory>
            <outputDirectory>${file.separator}lib</outputDirectory>
            <includes>
                <include>${project.artifactId}-${project.version}.jar</include>
            </includes>
        </fileSet>
    </fileSets>
</assembly>

我们创建一个package文件夹,用来存在打包相关的文件信息,package.xml也放在其中。

手把手教你java项目如何使用startup.sh启动

1.2 编写start.sh脚本

因为我绝大多数部署在linux服务器,所以本文只提供.sh脚本,需要windows的.bat文件,请自行搜索吧。

start.sh做了什么?

  • 获取java环境变量
  • 指定了jvm参数
  • 组装启动命令
  • 执行组装好的命令

完整的start.sh如下所示

#!/bin/bash
error_exit ()
{
    echo "ERROR: $1 !!"
    exit 1
}
[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=$HOME/jdk/java
[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/java
[ ! -e "$JAVA_HOME/bin/java" ] && unset JAVA_HOME

if [ -z "$JAVA_HOME" ]; then
  if $darwin; then

    if [ -x '/usr/libexec/java_home' ] ; then
      export JAVA_HOME=`/usr/libexec/java_home`

    elif [ -d "/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home" ]; then
      export JAVA_HOME="/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home"
    fi
  else
    JAVA_PATH=`dirname $(readlink -f $(which javac))`
    if [ "x$JAVA_PATH" != "x" ]; then
      export JAVA_HOME=`dirname $JAVA_PATH 2>/dev/null`
    fi
  fi
  if [ -z "$JAVA_HOME" ]; then
        error_exit "Please set the JAVA_HOME variable in your environment, We need java(x64)! jdk8 or later is better!"
  fi
fi

export SERVER="rob-necessities-gateway"

export JAVA_HOME
export JAVA="$JAVA_HOME/bin/java"
export BASE_DIR=`cd $(dirname $0)/..; pwd`/${SERVER}

#===========================================================================================
# JVM Configuration
#===========================================================================================
JAVA_OPT="${JAVA_OPT} -Xms512m -Xmx512m -Xmn256m"

JAVA_MAJOR_VERSION=$($JAVA -version 2>&1 | sed -E -n 's/.* version "([0-9]*).*$/\1/p')
if [[ "$JAVA_MAJOR_VERSION" -ge "9" ]] ; then
  JAVA_OPT="${JAVA_OPT} -Xlog:gc*:file=${BASE_DIR}/logs/gc.log:time,tags:filecount=10,filesize=102400"
else
  JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${JAVA_HOME}/lib/ext"
  JAVA_OPT="${JAVA_OPT} -Xloggc:${BASE_DIR}/logs/gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M"
fi

JAVA_OPT="${JAVA_OPT} -jar ${BASE_DIR}/lib/${SERVER}.jar"
JAVA_OPT="${JAVA_OPT} --server.max-http-header-size=524288"

echo "$JAVA ${JAVA_OPT}"

# start
nohup $JAVA ${JAVA_OPT} >> /dev/null 2>&1 &
echo "server is starting"

至此为止,准备工作就基本完成了,下面我们开始处理pom.xml文件。

1.3 编辑pom.xml

在pom文件的<build>标签下的<plugins>标签当中,添加如下打包插件内容:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>3.1.1</version>
    <configuration>
        <descriptors>
            <descriptor>./src/main/resources/package/package.xml</descriptor>
        </descriptors>
    </configuration>
    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

二、打包验证

经过前面的准备过程,我们直接进行打包验证,直接使用命令mvn install即可,我这里使用idea的界面来操作,选择install:

手把手教你java项目如何使用startup.sh启动

打包后的文件,在项目的target目录下,如下图所示:

手把手教你java项目如何使用startup.sh启动

其中这个zip文件是我们需要的,其内容如下所示是:

手把手教你java项目如何使用startup.sh启动

lib中是jar包。

三、部署验证

3.1 环境准备

我们将zip文件上传到服务器,解压后进行启动测试,解压命令如下:

[root@hecs-402944 opt]# unzip rob-necessities-gateway-0.0.1-SNAPSHOT-bin.zip 
Archive:  rob-necessities-gateway-0.0.1-SNAPSHOT-bin.zip
   creating: rob-necessities-gateway-0.0.1-SNAPSHOT/
   creating: rob-necessities-gateway-0.0.1-SNAPSHOT/lib/
  inflating: rob-necessities-gateway-0.0.1-SNAPSHOT/startup.sh  
  inflating: rob-necessities-gateway-0.0.1-SNAPSHOT/lib/rob-necessities-gateway-0.0.1-SNAPSHOT.jar 

注意: 此处必须说明一个问题,如果你装的是oracle的jdk,那么直接启动就没有问题了,但是如果你装的是openjdk,需要注意两点:

  • openjdk安装是否正确,通常需要两步安装过程

    安装jre:

    sudo yum install java-1.8.0-openjdk  -y
    

    安装jdk

    sudo yum install java-1.8.0-openjdk-devel  -y
    
  • 环境变量配置是够正确

    vi /etc/profile
    

    在其中添加环境变量

    export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.322.b06-1.el7_9.x86_64
    export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    export PATH=$PATH:$JAVA_HOME/bin
    

    不知道java的路径可以使用下面的命令和步骤查找:

    [root@hecs-402944 rob-necessities-gateway-0.0.1-SNAPSHOT]# which java
    /usr/bin/java
    [root@hecs-402944 rob-necessities-gateway-0.0.1-SNAPSHOT]# ls -lrt /usr/bin/java
    lrwxrwxrwx 1 root root 22 2月  25 11:04 /usr/bin/java -> /etc/alternatives/java
    [root@hecs-402944 rob-necessities-gateway-0.0.1-SNAPSHOT]# ls -lrt /etc/alternatives/java
    lrwxrwxrwx 1 root root 73 2月  25 11:04 /etc/alternatives/java -> /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.322.b06-1.el7_9.x86_64/jre/bin/java
    

    其中的/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.322.b06-1.el7_9.x86_64即是安装路径。

3.2 启动

进入解压后的项目文件夹中,执行脚本命令:

[root@hecs-402944 rob-necessities-gateway-0.0.1-SNAPSHOT]# ./startup.sh 
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.322.b06-1.el7_9.x86_64/bin/java  -Xms512m -Xmx512m -Xmn256m -Djava.ext.dirs=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.322.b06-1.el7_9.x86_64/jre/lib/ext:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.322.b06-1.el7_9.x86_64/lib/ext -Xloggc:/opt/rob-necessities-gateway/logs/gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -jar /opt/rob-necessities-gateway/lib/rob-necessities-gateway.jar --server.max-http-header-size=524288
server is starting

注意,如果发现没有任何变化,可以将输出的命令行直接执行,看看报错内容,如下所示:

[root@hecs-402944 rob-necessities-gateway-0.0.1-SNAPSHOT]# /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.322.b06-1.el7_9.x86_64/bin/java  -Xms512m -Xmx512m -Xmn256m -Djava.ext.dirs=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.322.b06-1.el7_9.x86_64/jre/lib/ext:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.322.b06-1.el7_9.x86_64/lib/ext -Xloggc:/opt/rob-necessities-gateway/logs/gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -jar /opt/rob-necessities-gateway/lib/rob-necessities-gateway.jar --server.max-http-header-size=524288
Error: Unable to access jarfile /opt/rob-necessities-gateway/lib/rob-necessities-gateway.jar

报错内容是没有找到此jar包rob-necessities-gateway.jar,原因一目了然了,我们的jar包是带有版本号的:

手把手教你java项目如何使用startup.sh启动

如何修改?

注意我们前面提到得package.xml文件,如下所示位置:

手把手教你java项目如何使用startup.sh启动

红色框内的两部分其实分别是pom.xml的项目名和项目版本,两部分组合生成最终jar包的名称。

所以我们在startup.sh当中的配置要和这个保持一致,即

export SERVER="rob-necessities-gateway-0.0.1-SNAPSHOT"

前面的startup.sh之所以放错,是为了增加大家的印象,不要拿过去直接用,导致后面遇到问题不知如何下手。


经过上面全部过程,就能够成功启动了,成功后项目文件夹会生成其日志文件:

手把手教你java项目如何使用startup.sh启动

手把手教你java项目如何使用startup.sh启动

本文到此全部结束!希望对您有所帮助。

本文项目代码gitee地址: gitee.com/wei_rong_xi…