如何在Linux系统中将Spring Boot应用程序打包为可执行jar as a Service ?这是推荐的方法吗,还是应该将这个应用程序转换为war并将其安装到Tomcat中?

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

我正在寻找的是一般的建议/方向或样本init。D脚本,如果我的方法与可执行jar是适当的。


当前回答

以下是针对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

OR

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

其他回答

我自己刚刚抽出时间来做这件事,所以下面是到目前为止我在CentOS初始化方面的进展。D业务控制器脚本。到目前为止,它工作得很好,但我不是leet 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 \
        --spring.config.location=file:$APP_HOME/config/   \
        < /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

当停止时,它将尝试使用弹簧引导驱动器来执行受控关机。但是,如果没有配置执行器或未能在合理的时间范围内关闭(我给它5秒,这真的有点短),进程将被杀死。

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

作为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>

确保exe和xml以及jar文件在同一个文件夹中。

在此之后,在管理员权限下打开命令提示符并将其安装到windows服务。

your-app.exe install
eg -> D:\Springboot\your-app.exe install

如果失败了

Error: Registry key 'Software\JavaSoft\Java Runtime Environment'\CurrentVersion' has value '1.8', but '1.7' is required.

然后试试下面的方法:

Delete java.exe, javaw.exe and javaws.exe from C:\Windows\System32

就是这样:).

在windows下卸载服务

your-app.exe uninstall

查看/运行/停止服务: win+r并输入Administrative tools,然后从中选择服务。然后右击选择选项-运行/停止

创建一个名为your-app的脚本。服务(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

参考文献

在这里输入链接描述

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

让我们假设你正在使用systemd(现在任何现代发行版都是这样):

首先,在/etc/systemd/system目录下创建一个服务文件,例如javaservice。服务内容如下:

[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应用程序设置为系统服务的最非侵入性和最干净的方法。

我特别喜欢这个解决方案的地方在于,您不需要安装和配置任何其他软件。所提供的systemd为您完成所有工作,您的服务就像任何其他系统服务一样。我现在在生产环境中使用了一段时间,在各种发行版上,它就像你期望的那样工作。

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

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

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

我调用java -jar是因为它更灵活。我还试着把ExecStart=spring-mvc。战争,但即使是可执行的,我得到'Exec格式错误'

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

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 \
        -Dlog4j.configurationFile=log4j2-spring.xml \
        -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector \
        -Dspring.profiles.active=dev \
        -Denvironment-type=dev \
        -XX:+UseConcMarkSweepGC \
        -XX:CMSInitiatingOccupancyFraction=80 \
        -XX:NewSize=756m \
        -XX:MetaspaceSize=256m \
        -Dsun.net.inetaddr.ttl=5 \
        -Xloggc:/var/log/spring-mvc/gc.log \
        -verbose:gc \
        -verbosegc \
        -XX:+DisableExplicitGC \
        -XX:+PrintGCDetails \
        -XX:+PrintGCDateStamps \
        -XX:+PreserveFramePointer \
        -XX:+StartAttachListener \
        -Xms1024m \
        -Xmx1024m \
        -XX:+HeapDumpOnOutOfMemoryError \
        -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 -将应用程序的syslog输入重定向到特定的文件夹/文件

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

logrotate

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 gc

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
}