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

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

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


当前回答

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

其他回答

您还可以使用监控器,这是一个非常方便的守护进程,可以用来轻松地控制服务。这些服务是由简单的配置文件定义的,这些配置文件定义了在哪个目录下哪个用户执行什么,等等,有无数的选项。supervisor ord的语法非常简单,所以它是编写SysV初始化脚本的一个很好的替代方案。

这里有一个简单的监督配置文件,用于您试图运行/控制的程序。(把这个放到/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

要控制应用程序,你需要执行监控器ctl,它会提示你启动、停止和状态你的应用程序。

CLI

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

如果监控器守护进程已经在运行,并且您已经为您的服务添加了配置,而没有重新启动守护进程,那么您可以在监控器shell中简单地执行一个重读和更新命令。

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

Following up on Chad's excellent answer, if you get an error of "Error: Could not find or load main class" - and you spend a couple hours trying to troubleshoot it, whether your executing a shell script that starts your java app or starting it from systemd itself - and you know your classpath is 100% correct, e.g. manually running the shell script works as well as running what you have in systemd execstart. Be sure you're running things as the correct user! In my case, I had tried different users, after quite a while of troubleshooting - i finally had a hunch, put root as the user - voila, the app started correctly. After determining it was a wrong user issue, I chown -R user:user the folder and subfolders and the app ran correctly as the specified user and group so no longer needed to run it as root (bad security).

对于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>

下面是一个脚本,它将可执行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

例子:

如果你想使用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清洁包,做一个符号链接ln -s /…/myapp.jar /etc/init.chmod +x /etc/init. D /myapp,使其可执行启动myapp服务(Ubuntu服务器)