Spring Boot应用程序即服务

Mar*_*szS 179 service startup init.d spring-boot

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

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

我正在寻找的是一般建议/方向或示例init.d脚本,如果我使用可执行jar的方法是正确的.

cha*_*had 128

以下适用于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
Run Code Online (Sandbox Code Playgroud)

要么

sudo ln -s ~/myproject/build/libs/myapp-1.0.jar /etc/init.d/myapp_servicename
Run Code Online (Sandbox Code Playgroud)

之后你就可以照常做了

/etc/init.d/myapp start
Run Code Online (Sandbox Code Playgroud)

然后根据需要在启动时启动/停止应用程序的任何运行级别设置链接.


作为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
Run Code Online (Sandbox Code Playgroud)


参考

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

  • 这个答案**只适用于当前的1.3里程碑,尚未发布.1.1和1.2分支机构需要在这里检查其他响应. (5认同)
  • 你知道怎么把Spring的参数如`-Dspring.profiles.active = prod`传递给这些服务吗?问题 - http://stackoverflow.com/questions/31242291/add-additional-parameters-to-spring-boot-app (4认同)
  • “完全可执行的 JAR”方法如何工作?我使用的是CentOS 6.6。我将 `<executable>true</executable>` 添加到我的 `pom.xml` 中,但是打包的 JAR 文件不执行(... `./myapp.jar ... 无法执行二进制文件`。) (2认同)
  • 我无法停止spring-boot应用程序.`/etc/init.d stop`没有停止应用程序,它试图再次启动它. (2认同)
  • 如果你想监视进程并重新启动它,如果它在没有编写系统守护进程的情况下死掉,请查看http://patrickgrimard.com/2014/06/06/bootiful-spring-apps-with-supervisor/ (2认同)

ygl*_*odt 97

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

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

首先,使用以下内容创建一个/etc/systemd/system名为的服务文件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
Run Code Online (Sandbox Code Playgroud)

其次,通知systemd新的服务文件:

systemctl daemon-reload
Run Code Online (Sandbox Code Playgroud)

并启用它,因此它在启动时运行:

systemctl enable javaservice.service
Run Code Online (Sandbox Code Playgroud)

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

systemctl start javaservice
systemctl stop javaservice
systemctl restart javaservice
systemctl status javaservice
Run Code Online (Sandbox Code Playgroud)

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

我特别喜欢这个解决方案的事实是你不需要安装和配置任何其他软件.发货systemd为您完成所有工作,您的服务就像任何其他系统服务一样.我现在在生产中使用它一段时间,在不同的发行版上,它只是按照你的预期工作.

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

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

  • 为了获得正确的启动顺序,您可能需要将排序语句添加到“[Unit]”部分,例如“After=mysql.service”、“Before=apache2.service”。 (3认同)
  • 使用Spring Boot 1.3+,您可以生成一个完全可执行的war文件,因此不需要java -jar ...位,只需在此处使用文件名即可。 (2认同)
  • 我更喜欢使用完整的 java 命令行,因为这样您就可以添加 jvm 参数。 (2认同)
  • 对于其他人来说,`SuccessExitStatus=143` 意味着“将退出状态 143(对应于 SIGTERM)视为该服务的正常退出状态” (2认同)

fla*_*ini 55

您还可以使用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
Run Code Online (Sandbox Code Playgroud)

要控制应用程序,您需要执行supervisorctl,它会向您显示一个提示,您可以在其中启动,停止,状态为yourapp.

CLI

# sudo supervisorctl
yourapp             RUNNING   pid 123123, uptime 1 day, 15:00:00
supervisor> stop yourapp
supervisor> start yourapp
Run Code Online (Sandbox Code Playgroud)

如果supervisord守护进程已经在运行,并且您已经添加的配置为您serivce无需重新启动后台程序,你可以简单地做一个reread,并update在命令supervisorctl外壳.

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


Ste*_*eve 17

我自己就是这样做的,所以以下是我目前在CentOS init.d服务控制器脚本方面的地方.到目前为止它工作得非常好,但我不是let 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
Run Code Online (Sandbox Code Playgroud)

我正在使用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
Run Code Online (Sandbox Code Playgroud)

如您所见,它调用初始配置脚本来设置环境变量,然后调用我用来重新启动所有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
Run Code Online (Sandbox Code Playgroud)

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

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

  • 无需编写自己的启动/停止脚本.这是从Spring Boot 1.3及更高版本开始提供的.有关更多详细信息,请参阅http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#deployment-install. (3认同)

Ben*_*n M 13

如果你想在Spring Boot Maven Plugin 1.3.0.M2中使用Spring Boot 1.2.5,这里有一个解决方案:

<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>
Run Code Online (Sandbox Code Playgroud)

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


voo*_*oor 8

我知道这是一个较老的问题,但我想提出另一种方法,即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>
Run Code Online (Sandbox Code Playgroud)


Aru*_*dev 7

作为 Windows 服务

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

 http://repo.jenkins-ci.org/releases/com/sun/winsw/winsw/2.1.2/
Run Code Online (Sandbox Code Playgroud)

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

winsw.exe -> your-app.exe
Run Code Online (Sandbox Code Playgroud)

现在创建一个 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>
Run Code Online (Sandbox Code Playgroud)

确保exexml以及jar在同一文件夹中。

在管理员权限中打开命令提示符后,将其安装到 Windows 服务中。

your-app.exe install
eg -> D:\Springboot\your-app.exe install
Run Code Online (Sandbox Code Playgroud)

如果失败

Error: Registry key 'Software\JavaSoft\Java Runtime Environment'\CurrentVersion' has value '1.8', but '1.7' is required.
Run Code Online (Sandbox Code Playgroud)

然后尝试以下操作:

Delete java.exe, javaw.exe and javaws.exe from C:\Windows\System32
Run Code Online (Sandbox Code Playgroud)

就是这样 :) 。

在 windows 中卸载服务

your-app.exe uninstall
Run Code Online (Sandbox Code Playgroud)

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


Use*_*er0 5

这是一个将可执行 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
Run Code Online (Sandbox Code Playgroud)

例子: 在此处输入图片说明


Rad*_*der 5

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

\n\n

我称之为 java -jar 因为它更灵活。还尝试放置 ExecStart=spring-mvc.war 但即使可执行,我也收到“Exec 格式错误”

\n\n

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

\n\n
cat /etc/systemd/system/spring-mvc.service \n[Unit]\nDescription=Spring MVC Java Service\n\n[Service]\nUser=spring-mvc\n# The configuration file application.properties should be here:\nWorkingDirectory=/usr/local/spring-mvc\n\n\n# Run ExecStartPre with root-permissions\nPermissionsStartOnly=true\n\nExecStartPre=-/bin/mkdir -p /var/log/spring-mvc\n\n\nExecStartPre=/bin/chown -R spring-mvc:syslog /var/log/spring-mvc\nExecStartPre=/bin/chmod -R 775 /var/log/spring-mvc\n\n\n\n#https://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart=\nExecStart=/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\n\nSuccessExitStatus=143\nStandardOutput=journal\nStandardError=journal\n\n\nKillSignal=SIGINT\nTimeoutStopSec=20\nRestart=always\nRestartSec=5\nStartLimitInterval=0\nStartLimitBurst=10\n\nLimitNOFILE=500000\nLimitNPROC=500000\n\n#https://www.freedesktop.org/software/systemd/man/systemd.exec.html#LimitCPU=\n#LimitCPU=, LimitFSIZE=, LimitDATA=, LimitSTACK=, LimitCORE=, LimitRSS=, LimitNOFILE=, LimitAS=, LimitNPROC=, LimitMEMLOCK=, LimitLOCKS=, LimitSIGPENDING=, LimitMSGQUEUE=, LimitNICE=, LimitRTPRIO=, LimitRTTIME=\xc2\xb6\n\nSyslogIdentifier=spring-mvc\n\n[Install]\nWantedBy=multi-user.target\n\n\n# https://www.freedesktop.org/software/systemd/man/journalctl.html\n#check logs --- journalctl -u spring-mvc -f -o cat\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
cat /etc/rsyslog.d/30-spring-mvc.conf \nif $programname == 'spring-mvc' then /var/log/spring-mvc/spring-mvc.log\n& stop\n
Run Code Online (Sandbox Code Playgroud)\n\n

对数旋转

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

对数旋转GC

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