Spring Boot 应用程序即服务

2024-10-18 09:00:00
admin
原创
72
摘要:问题描述:如何很好地配置将 Spring Boot 应用程序打包为可执行 jar 作为 Linux 系统中的服务?这是推荐的方法吗,还是我应该将此应用程序转换为 war 并将其安装到 Tomcat 中?目前,我可以从会话中运行 Spring boot 应用程序screen,这很好,但需要在服务器重启后手动启动...

问题描述:

如何很好地配置将 Spring Boot 应用程序打包为可执行 jar 作为 Linux 系统中的服务?这是推荐的方法吗,还是我应该将此应用程序转换为 war 并将其安装到 Tomcat 中?

目前,我可以从会话中运行 Spring boot 应用程序screen,这很好,但需要在服务器重启后手动启动。

如果我对可执行jar 的方法正确,那么我正在寻找一般的建议/指导或示例init.d脚本。


解决方案 1:

以下适用于springboot 1.3及以上版本:

作为 init.d 服务

可执行 jar 包含常用的启动、停止、重启和状态命令。它还会在常用的 /var/run 目录中设置 PID 文件,并默认在常用的 /var/log 目录中记录日志。

你只需要将你的 jar 符号链接到 /etc/init.d 中,就像这样

sudo link -s /var/myapp/myapp.jar /etc/init.d/myapp

或者

sudo ln -s ~/myproject/build/libs/myapp-1.0.jar /etc/init.d/myapp_servicename

之后你可以做通常的事情

/etc/init.d/myapp start

然后,如果需要,在您希望应用程序在启动时启动/停止的运行级别中设置一个链接。


作为 systemd 服务

要运行安装在 var/myapp 中的 Spring Boot 应用程序,您可以在 /etc/systemd/system/myapp.service 中添加以下脚本:

[Unit]
Description=myapp
After=syslog.target

[Service]
ExecStart=/var/myapp/myapp.jar

[Install]
WantedBy=multi-user.target

注意:如果您使用此方法,请不要忘记使 jar 文件本身可执行(使用 chmod +x),否则它将失败并出现错误“权限被拒绝”。

参考

http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/html/deployment-install.html#deployment-service

解决方案 2:

以下是在 Linux 中将 Java 应用程序安装为系统服务的最简单方法。

该解决方案使用systemd,现在任何现代发行版都使用,因此不需要安装任何其他工具或服务。

首先,创建一个/etc/systemd/system名为 eg的服务文件javaservice.service,内容如下:

[Unit]
Description=Java Service

[Service]
User=nobody
# The configuration file application.properties should be here:
WorkingDirectory=/data 
ExecStart=/usr/bin/java -Xmx256m -jar application.jar --server.port=8081
SuccessExitStatus=143
TimeoutStopSec=10
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

systemd二、新服务文件的通知:

systemctl daemon-reload

并启用它,以便它在启动时运行:

systemctl enable javaservice.service

最后,您可以使用以下命令来启动/停止新服务:

systemctl start javaservice
systemctl stop javaservice
systemctl restart javaservice
systemctl status javaservice

如果您正在使用systemd,这是将 Java 应用程序设置为系统服务的最非侵入性和最干净的方法。

我特别喜欢这个解决方案的一点是,你不需要安装和配置任何其他软件。Shipmentsystemd会为你完成所有工作,你的服务就像任何其他系统服务一样运行。我在各种发行版上使用它已经有一段时间了,它的工作方式与你预期的一样。

另一个优点是,通过使用/usr/bin/java,您可以轻松添加jvm诸如之类的参数-Xmx256m

另请阅读systemdSpring Boot 官方文档中的部分:
http ://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html

解决方案 3:

您还可以使用supervisord,这是一个非常方便的守护进程,可用于轻松控制服务。这些服务由简单的配置文件定义,定义在哪个目录中以哪个用户执行什么操作等等,有无数种选择。supervisord语法非常简单,因此它是编写 SysV init 脚本的非常好的替代方案。

这是您要运行/控制的程序的简单Supervisord配置文件。(将其放入/etc/supervisor/conf.d/yourapp.conf

/etc/supervisor/conf.d/yourapp.conf

[program:yourapp]
command=/usr/bin/java -jar /path/to/application.jar
user=usertorun
autostart=true
autorestart=true
startsecs=10
startretries=3
stdout_logfile=/var/log/yourapp-stdout.log
stderr_logfile=/var/log/yourapp-stderr.log

要控制应用程序,您需要执行supervisorctl,它将向您显示一个提示,您可以在其中启动、停止、查看应用程序的状态。

命令行界面

# sudo supervisorctl
yourapp             RUNNING   pid 123123, uptime 1 day, 15:00:00
supervisor> stop yourapp
supervisor> start yourapp

如果supervisord守护进程已在运行,并且您已添加了服务配置而无需重新启动守护进程,则您只需在 shell 中执行reread和命令即可。update`supervisorctl`

这确实为您提供了使用 SysV Init 脚本所具有的所有灵活性,但易于使用和控制。请查看文档。

解决方案 4:

我刚刚开始自己​​做这件事,所以以下是我目前在 CentOS init.d 服务控制器脚本方面的进展。到目前为止,它运行得很好,但我不是 Bash 黑客,所以我确信还有改进的空间,所以欢迎提出改进它的想法。

首先,我/data/svcmgmt/conf/my-spring-boot-api.sh为每个服务准备了一个简短的配置脚本,用于设置环境变量。

#!/bin/bash
export JAVA_HOME=/opt/jdk1.8.0_05/jre
export APP_HOME=/data/apps/my-spring-boot-api
export APP_NAME=my-spring-boot-api
export APP_PORT=40001

我正在使用 CentOS,因此为了确保我的服务在服务器重启后启动,我有一个服务控制脚本/etc/init.d/my-spring-boot-api

#!/bin/bash
# description: my-spring-boot-api start stop restart
# processname: my-spring-boot-api
# chkconfig: 234 20 80

. /data/svcmgmt/conf/my-spring-boot-api.sh

/data/svcmgmt/bin/spring-boot-service.sh $1

exit 0

如您所见,它调用初始配置脚本来设置环境变量,然后调用共享脚本,我使用该脚本重新启动所有 Spring Boot 服务。该共享脚本是所有内容的核心所在:

#!/bin/bash

echo "Service [$APP_NAME] - [$1]"

echo "    JAVA_HOME=$JAVA_HOME"
echo "    APP_HOME=$APP_HOME"
echo "    APP_NAME=$APP_NAME"
echo "    APP_PORT=$APP_PORT"

function start {
    if pkill -0 -f $APP_NAME.jar > /dev/null 2>&1
    then
        echo "Service [$APP_NAME] is already running. Ignoring startup request."
        exit 1
    fi
    echo "Starting application..."
    nohup $JAVA_HOME/bin/java -jar $APP_HOME/$APP_NAME.jar \n        --spring.config.location=file:$APP_HOME/config/   \n        < /dev/null > $APP_HOME/logs/app.log 2>&1 &
}

function stop {
    if ! pkill -0 -f $APP_NAME.jar > /dev/null 2>&1
    then
        echo "Service [$APP_NAME] is not running. Ignoring shutdown request."
        exit 1
    fi

    # First, we will try to trigger a controlled shutdown using 
    # spring-boot-actuator
    curl -X POST http://localhost:$APP_PORT/shutdown < /dev/null > /dev/null 2>&1

    # Wait until the server process has shut down
    attempts=0
    while pkill -0 -f $APP_NAME.jar > /dev/null 2>&1
    do
        attempts=$[$attempts + 1]
        if [ $attempts -gt 5 ]
        then
            # We have waited too long. Kill it.
            pkill -f $APP_NAME.jar > /dev/null 2>&1
        fi
        sleep 1s
    done
}

case $1 in
start)
    start
;;
stop)
    stop
;;
restart)
    stop
    start
;;
esac
exit 0

停止时,它将尝试使用 Spring Boot Actuator 执行受控关闭。但是,如果未配置 Actuator 或无法在合理的时间内关闭(我给它 5 秒,这实际上有点短),则该进程将被终止。

此外,脚本还假设运行应用程序的 Java 进程是进程详细信息文本中唯一包含“my-spring-boot-api.jar”的进程。在我的环境中,这是一个安全的假设,意味着我不需要跟踪 PID。

解决方案 5:

如果您想将 Spring Boot 1.2.5 与 Spring Boot Maven Plugin 1.3.0.M2 一起使用,请参阅以下解决方案:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.2.5.RELEASE</version>
</parent>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>1.3.0.M2</version>
            <configuration>
                <executable>true</executable>
            </configuration>
        </plugin>
    </plugins>
</build>

<pluginRepositories>
    <pluginRepository>
        <id>spring-libs-milestones</id>
        <url>http://repo.spring.io/libs-milestone</url>
    </pluginRepository> 
</pluginRepositories>

然后按通常方式编译:mvn clean package,创建符号链接ln -s /.../myapp.jar /etc/init.d/myapp,使其可执行chmod +x /etc/init.d/myapp并启动它service myapp start(使用 Ubuntu Server)

解决方案 6:

我知道这是一个老问题,但我想提出另一种方法,即appassembler-maven-plugin。 以下是我的 POM 中的相关部分,其中包含许多我们认为有用的附加选项值:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>appassembler-maven-plugin</artifactId>
    <configuration>
        <generateRepository>true</generateRepository>
        <repositoryLayout>flat</repositoryLayout>
        <useWildcardClassPath>true</useWildcardClassPath>
        <includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
        <configurationDirectory>config</configurationDirectory>
        <target>${project.build.directory}</target>
        <daemons>
            <daemon>
                <id>${installer-target}</id>
                <mainClass>${mainClass}</mainClass>
                <commandLineArguments>
                    <commandLineArgument>--spring.profiles.active=dev</commandLineArgument>
                    <commandLineArgument>--logging.config=${rpmInstallLocation}/config/${installer-target}-logback.xml</commandLineArgument>
                </commandLineArguments>
                <platforms>
                    <platform>jsw</platform>
                </platforms>
                <generatorConfigurations>
                    <generatorConfiguration>
                        <generator>jsw</generator>
                        <includes>
                            <include>linux-x86-64</include>
                        </includes>
                        <configuration>
                            <property>
                                <name>wrapper.logfile</name>
                                <value>logs/${installer-target}-wrapper.log</value>
                            </property>
                            <property>
                                <name>wrapper.logfile.maxsize</name>
                                <value>5m</value>
                            </property>
                            <property>
                                <name>run.as.user.envvar</name>
                                <value>${serviceUser}</value>
                            </property>
                            <property>
                                <name>wrapper.on_exit.default</name>
                                <value>RESTART</value>
                            </property>
                        </configuration>
                    </generatorConfiguration>
                </generatorConfigurations>
                <jvmSettings>
                    <initialMemorySize>256M</initialMemorySize>
                    <maxMemorySize>1024M</maxMemorySize>
                    <extraArguments>
                        <extraArgument>-server</extraArgument>
                    </extraArguments>
                </jvmSettings>
            </daemon>
        </daemons>
    </configuration>
    <executions>
        <execution>
            <id>generate-jsw-scripts</id>
            <phase>package</phase>
            <goals>
                <goal>generate-daemons</goal>
            </goals>
        </execution>
    </executions>
</plugin>

解决方案 7:

作为 Windows 服务

如果你希望它在 Windows 机器上运行,请从以下位置下载 winsw.exe

 http://repo.jenkins-ci.org/releases/com/sun/winsw/winsw/2.1.2/

然后将其重命名为 jar 文件名(例如:your-app .jar)

winsw.exe -> your-app.exe

现在创建一个 xml 文件your-app.xml并将以下内容复制到该文件中

<?xml version="1.0" encoding="UTF-8"?>
<service>
     <id>your-app</id>
     <name>your-app</name>
     <description>your-app as a Windows Service</description>
     <executable>java</executable>
     <arguments>-jar "your-app.jar"</arguments>
     <logmode>rotate</logmode>
</service>

确保exexmljar位于同一文件夹中。

此后以管理员权限打开命令提示符并将其安装到 Windows 服务。

your-app.exe install
eg -> D:Springbootyour-app.exe install

如果失败

Error: Registry key 'SoftwareJavaSoftJava Runtime Environment'CurrentVersion' has value '1.8', but '1.7' is required.

然后尝试以下操作:

Delete java.exe, javaw.exe and javaws.exe from C:WindowsSystem32

就是这样 :) 。

在 Windows 中卸载服务

your-app.exe uninstall

要查看/运行/停止服务:
win+r并输入管理工具,然后从中选择服务。然后右键单击选择选项 - 运行/停止

解决方案 8:

这是一个将可执行 jar 文件部署为 systemd 服务的脚本。

它为服务和.service 文件创建一个用户,并将 jar 文件放在 /var 下,并对权限进行一些基本锁定。

#!/bin/bash

# Argument: The jar file to deploy
APPSRCPATH=$1

# Argument: application name, no spaces please, used as folder name under /var
APPNAME=$2

# Argument: the user to use when running the application, may exist, created if not exists
APPUSER=$3

# Help text
USAGE="
Usage: sudo $0 <jar-file> <app-name> <runtime-user>
If an app with the name <app-name> already exist, it is stopped and deleted.
If the <runtime-user> does not already exist, it is created.
"

# Check that we are root
if [ ! "root" = "$(whoami)" ]; then
    echo "Must be root. Please use e.g. sudo"
    echo "$USAGE"
    exit
fi

# Check arguments
if [ "$#" -ne 3 -o ${#APPSRCPATH} = 0 -o ${#APPNAME} = 0 -o ${#APPUSER} = 0 ]; then
    echo "Incorrect number of parameters."
    echo "$USAGE"
    exit
fi

if [ ! -f $APPSRCPATH ]; then
    echo "Can't find jar file $APPSRCPATH"
    echo "$USAGE"
    exit
fi

# Infered values
APPFILENAME=$(basename $APPSRCPATH)
APPFOLDER=/var/javaapps/$APPNAME
APPDESTPATH=$APPFOLDER/$APPFILENAME

# Stop the service if it already exist and is running
systemctl stop $APPNAME >/dev/null 2>&1

# Create the app folder, deleting any previous content
rm -fr $APPFOLDER
mkdir -p $APPFOLDER

# Create the user if it does not exist
if id "$APPUSER" >/dev/null 2>&1; then
    echo "Using existing user $APPUSER"
else
    adduser --disabled-password --gecos "" $APPUSER
    echo "Created user $APPUSER"
fi

# Place app in app folder, setting owner and rights
cp $APPSRCPATH $APPDESTPATH
chown $APPUSER $APPDESTPATH
chmod 500 $APPDESTPATH
echo "Added or updated the $APPDESTPATH file"

# Create the .service file used by systemd
echo "
[Unit]
Description=$APPNAME
After=syslog.target
[Service]
User=$APPUSER
ExecStart=/usr/bin/java -jar $APPDESTPATH
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
" > /etc/systemd/system/$APPNAME.service
echo "Created the /etc/systemd/system/$APPNAME.service file"

# Reload the daemon
systemctl daemon-reload

# Start the deployed app
systemctl start $APPNAME
systemctl status $APPNAME

例子:
在此处输入图片描述

解决方案 9:

我最终为 WAR/JAR 布局做了 systemd 服务

我调用 java -jar 是因为它更灵活。还尝试输入 ExecStart=spring-mvc.war,但尽管是可执行文件,我还是收到“Exec 格式错误”

无论如何,现在,systemd 存在于所有发行版中,并提供了一个很好的解决方案来重定向日志(当您的服务甚至没有启动 log4j 文件位置时,syserr 很重要:))。

cat /etc/systemd/system/spring-mvc.service 
[Unit]
Description=Spring MVC Java Service

[Service]
User=spring-mvc
# The configuration file application.properties should be here:
WorkingDirectory=/usr/local/spring-mvc


# Run ExecStartPre with root-permissions
PermissionsStartOnly=true

ExecStartPre=-/bin/mkdir -p /var/log/spring-mvc


ExecStartPre=/bin/chown -R spring-mvc:syslog /var/log/spring-mvc
ExecStartPre=/bin/chmod -R 775 /var/log/spring-mvc



#https://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart=
ExecStart=/usr/bin/java \n        -Dlog4j.configurationFile=log4j2-spring.xml \n        -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector \n        -Dspring.profiles.active=dev \n        -Denvironment-type=dev \n        -XX:+UseConcMarkSweepGC \n        -XX:CMSInitiatingOccupancyFraction=80 \n        -XX:NewSize=756m \n        -XX:MetaspaceSize=256m \n        -Dsun.net.inetaddr.ttl=5 \n        -Xloggc:/var/log/spring-mvc/gc.log \n        -verbose:gc \n        -verbosegc \n        -XX:+DisableExplicitGC \n        -XX:+PrintGCDetails \n        -XX:+PrintGCDateStamps \n        -XX:+PreserveFramePointer \n        -XX:+StartAttachListener \n        -Xms1024m \n        -Xmx1024m \n        -XX:+HeapDumpOnOutOfMemoryError \n        -jar spring-mvc.war

SuccessExitStatus=143
StandardOutput=journal
StandardError=journal


KillSignal=SIGINT
TimeoutStopSec=20
Restart=always
RestartSec=5
StartLimitInterval=0
StartLimitBurst=10

LimitNOFILE=500000
LimitNPROC=500000

#https://www.freedesktop.org/software/systemd/man/systemd.exec.html#LimitCPU=
#LimitCPU=, LimitFSIZE=, LimitDATA=, LimitSTACK=, LimitCORE=, LimitRSS=, LimitNOFILE=, LimitAS=, LimitNPROC=, LimitMEMLOCK=, LimitLOCKS=, LimitSIGPENDING=, LimitMSGQUEUE=, LimitNICE=, LimitRTPRIO=, LimitRTTIME=¶

SyslogIdentifier=spring-mvc

[Install]
WantedBy=multi-user.target


# https://www.freedesktop.org/software/systemd/man/journalctl.html
#check logs --- journalctl -u spring-mvc -f -o cat

rsyslog-将系统日志输入从应用程序重定向到特定文件夹/文件

cat /etc/rsyslog.d/30-spring-mvc.conf 
if $programname == 'spring-mvc' then /var/log/spring-mvc/spring-mvc.log
& stop

日志旋转

cat /etc/logrotate.d/spring-mvc.conf 
/var/log/spring-mvc/spring-mvc.log
{
    daily
    rotate 30
    maxage 30
    copytruncate
    missingok
    notifempty
    compress
    dateext
    dateformat _%Y-%m-%d_%H-%M
    delaycompress
    create 644 spring-mvc syslog
    su spring-mvc syslog
}

logrotate 垃圾回收

cat /etc/logrotate.d/spring-mvc-gc.conf 
/var/log/spring-mvc/gc.log
{
    daily
    rotate 30
    maxage 30
    copytruncate
    missingok
    notifempty
    compress
    dateext
    dateformat _%Y-%m-%d_%H-%M
    delaycompress
    create 644 spring-mvc syslog
    su spring-mvc syslog
}

解决方案 10:

我的 Centos 6 / RHEL 的 SysVInit 脚本(尚不理想)。此脚本需要ApplicationPidListener。

来源/etc/init.d/app

#!/bin/sh
#
# app Spring Boot Application 
#
# chkconfig:   345 20 80
# description: App Service
#           

### BEGIN INIT INFO
# Provides: App
# Required-Start: $local_fs $network
# Required-Stop: $local_fs $network
# Default-Start: 3 4 5 
# Default-Stop: 0 1 2 6
# Short-Description: Application
# Description:      
### END INIT INFO

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

exec="/usr/bin/java"
prog="app"
app_home=/home/$prog/
user=$prog

[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog

lockfile=/var/lock/subsys/$prog    
pid=$app_home/$prog.pid

start() {

    [ -x $exec ] || exit 5
    [ -f $config ] || exit 6
    # Check that networking is up.
    [ "$NETWORKING" = "no" ] && exit 1
    echo -n $"Starting $prog: "
    cd $app_home
    daemon --check $prog --pidfile $pid --user $user $exec $app_args &
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    killproc -p $pid $prog
    retval=$?
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    stop
    start
}

reload() {
    restart
}

force_reload() {
    restart
}

rh_status() {
    status -p $pid $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}

case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
        restart
        ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
        exit 2
esac
exit $?

示例配置文件/etc/sysconfig/app

exec=/opt/jdk1.8.0_05/jre/bin/java

user=myuser
app_home=/home/mysuer/

app_args="-jar app.jar"

pid=$app_home/app.pid

解决方案 11:

我正在尝试制作以“init.d”样式的 shell 脚本形式呈现的 springboot 应用程序,并在末尾附加一个压缩的 java 应用程序

通过将这些脚本从 /etc/init.d/spring-app 符​​号链接到 /opt/spring-app.jar 并将 jar 修改为可执行文件,可以执行“/etc/init.d/spring-app start”、“/etc/init.d/spring-app stop”以及其他操作,例如状态工作

据推测,由于 springboot 中的 init.d 样式脚本看起来具有必要的魔术字符串(例如# Default-Start: 2 3 4 5)chkconfig 能够将其添加为“服务”

但我想让它与 systemd 一起工作

为了使这个工作,我尝试了上面其他答案中的许多方法,但是在使用 Springboot 1.3 的 Centos 7.2 上,它们都没有起作用,大多数情况下它们会启动服务,但无法跟踪 pid

最后我发现,当 /etc/init.d 链接也存在时,下面的方法对我有用。应该安装类似于下面的文件/usr/lib/systemd/system/spring-app.service

[Unit]
Description=My loverly application
After=syslog.target 

[Service]
Type=forking
PIDFile=/var/run/spring-app/spring-app.pid
ExecStart=/etc/init.d/spring-app start
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

解决方案 12:

Spring Boot 项目中的 build.gradle 文件中需要进行以下配置。

构建.gradle

jar {
    baseName = 'your-app'
    version = version
}

springBoot {
    buildInfo()
    executable = true   
    mainClass = "com.shunya.App"
}

可执行文件=true

这是在 unix 系统(Centos 和 Ubuntu)上制作完全可执行 jar 所必需的

创建 .conf 文件

如果要配置自定义 JVM 属性或 Spring Boot 应用程序运行参数,那么您可以创建一个与 Spring Boot 应用程序名称同名的 .conf 文件,并将其与 jar 文件并行放置。

考虑到your-app.jar是您的Spring Boot应用程序的名称,那么您可以创建以下文件。

JAVA_OPTS="-Xms64m -Xmx64m"
RUN_ARGS=--spring.profiles.active=prod
LOG_FOLDER=/custom/log/folder

此配置将为 Spring Boot 应用程序设置 64 MB RAM 并激活产品配置文件。

在Linux中创建新用户

为了增强安全性,我们必须创建一个特定的用户来将 Spring Boot 应用程序作为服务运行。

创建新用户

sudo useradd -s /sbin/nologin springboot

在 Ubuntu / Debian 上,修改上述命令如下:

sudo useradd -s /usr/sbin/nologin springboot

设置密码

sudo passwd springboot

使 springboot 成为可执行文件的所有者

chown springboot:springboot your-app.jar

防止jar文件被修改

chmod 500 your-app.jar

这样就可以配置 jar 的权限,使得它不可被写入,只能由其所有者 springboot 读取或执行。

您可以选择使用更改属性(chattr)命令将您的 jar 文件设为不可变的。

sudo chattr +i your-app.jar

还应为相应的 .conf 文件设置适当的权限。.conf 只需要读取权限(八进制 400),而不是读取 + 执行(八进制 500)访问权限

chmod 400 your-app.conf

创建 Systemd 服务

/etc/systemd/system/your-app.service

[Unit]
Description=Your app description
After=syslog.target

[Service]
User=springboot
ExecStart=/var/myapp/your-app.jar
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

如果进程被操作系统终止,则自动重新启动

附加以下两个属性(Restart 和 RestartSec)以在失败时自动重新启动进程。

/etc/systemd/system/your-app.service

[Service]
User=springboot
ExecStart=/var/myapp/your-app.jar
SuccessExitStatus=143
Restart=always
RestartSec=30

此更改将使 Spring Boot 应用程序在发生故障时重新启动,延迟 30 秒。如果您使用 systemctl 命令停止服务,则不会重新启动。

系统启动时安排服务

要标记应用程序在系统启动时自动启动,请使用以下命令:

在系统启动时启用 Spring Boot 应用程序

sudo systemctl enable your-app.service

启动和停止服务

systemctl 可以在 Ubuntu 16.04 LTS 和 18.04 LTS 中使用来启动和停止该进程。

启动流程

sudo systemctl start your-app

停止进程

sudo systemctl stop your-app

参考

https://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html

解决方案 13:

对于这个问题,@PbxMan 的回答应该可以帮助您:

在 Linux 上将 Java 应用程序作为服务运行

编辑:

还有另一种不太好的方法在重启时启动进程,即使用 cron:

@reboot user-to-run-under /usr/bin/java -jar /path/to/application.jar

这可行,但无法为您的应用程序提供良好的启动/停止界面。kill无论如何,您仍然可以简化它...

解决方案 14:

我不知道使用 Java 应用程序执行此操作的“标准”压缩方法,但这绝对是个好主意(如果操作系统具有 keep-alive 和监控功能,您希望从中受益)。路线图上提供了 Spring Boot 工具支持(maven 和 gradle)中的一些功能,但目前您可能必须自己动手。我目前知道的最佳解决方案是Foreman,它具有声明性方法和一行命令,用于打包各种标准操作系统格式(monit、sys V、upstart 等)的 init 脚本。也有证据表明人们已经使用 gradle 设置了一些东西(例如这里)。

解决方案 15:

你正在使用 Maven 吗?那么你应该尝试 AppAssembler 插件:

应用程序组装器插件是一个 Maven 插件,用于生成启动 Java 应用程序的脚本。... 所有工件(依赖项 + 来自项目的工件)都添加到生成的 bin 脚本中的类路径中。

支持的平台:

Unix 变体

Windows NT(不支持 Windows 9x)

Java 服务包装器 (JSW)

参见: http: //mojo.codehaus.org/appassembler/appassembler-maven-plugin/index.html

解决方案 16:

接着Chad的出色回答,如果您收到“错误:找不到或加载主类”的错误- 并且您花了几个小时尝试对其进行故障排除,无论您是执行启动Java应用程序的shell脚本还是从systemd本身启动它 - 并且您知道您的类路径是100%正确的,例如手动运行shell脚本和运行systemd execstart中的脚本一样有效。 确保您以正确的用户身份运行!就我而言,我尝试了不同的用户,经过相当长一段时间的故障排除 - 我终于有了一个预感,将root作为用户 - 瞧,应用程序正确启动了。在确定这是一个错误的用户问题后,我chown -R user:user以指定的用户和组正确运行了文件夹和子文件夹以及应用程序,因此不再需要以root身份运行它(安全性差)。

解决方案 17:

在 systemd 单元文件中,您可以设置环境变量目录或通过EnvironmentFile。我建议以这种方式做事,因为它似乎是最少的摩擦。

示例单元文件

$ cat /etc/systemd/system/hello-world.service
[Unit]
Description=Hello World Service
After=systend-user-sessions.service

[Service]
EnvironmentFile=/etc/sysconfig/hello-world
Type=simple
ExecStart=/usr/bin/java ... hello-world.jar

然后设置一个文件,其中/etc/sysconfig/hello-world包含 Spring Boot 变量的大写名称。例如,名为的变量server.port将遵循以下形式SERVER_PORT作为环境变量:

$ cat /etc/sysconfig/hello-world
SERVER_PORT=8081

这里利用的机制是,Spring Boot 应用程序将获取属性列表,然后对其进行转换,将所有内容都大写,并用下划线替换点。Spring Boot 应用程序完成此过程后,它会查找匹配的环境变量,并使用找到的任何相应变量。

在 SO Q&A 中对此进行了更详细的介绍,标题为:如何通过环境变量设置名称中带有下划线的 Spring Boot 属性?

参考

  • 第四部分 Spring Boot 特性 - 24. 外部化配置

解决方案 18:

可以使用 Ubuntu 中的 Systemd 服务来完成

[Unit]
Description=A Spring Boot application
After=syslog.target

[Service]
User=baeldung
ExecStart=/path/to/your-app.jar SuccessExitStatus=143

[Install] 
WantedBy=multi-user.target

您可以点击此链接获取更详细的描述和不同的方法。http
://www.baeldung.com/spring-boot-app-as-a-service

解决方案 19:

创建一个名为 your-app.service (rest-app.service) 的脚本。我们应该将此脚本放在 /etc/systemd/system 目录中。以下是脚本的示例内容

[Unit]
Description=Spring Boot REST Application
After=syslog.target

[Service]
User=javadevjournal
ExecStart=/var/rest-app/restdemo.jar
SuccessExitStatus=200

[Install]
WantedBy=multi-user.target

下一个:

 service rest-app start

参考

在此处输入链接描述

解决方案 20:

对于 SpringBoot 2.4.4,除了
@ismael的说明之外

我在 maven pom.xml 中添加了以下内容,使其成为可执行 jar

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>               
            <configuration>
                <executable>true</executable>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用