如何在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

其他回答

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

下面是在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

创建一个名为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

参考文献

在这里输入链接描述

在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应用程序完成了这个过程,它就会寻找匹配的环境变量,并相应地使用找到的环境变量。

在这篇题为:如何通过环境变量在其名称中设置带有下划线的Spring Boot属性的SO Q&A中强调了更多细节?

参考文献

第四部分。弹簧引导功能- 24。外部化配置

我自己刚刚抽出时间来做这件事,所以下面是到目前为止我在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。