安装 Spring Boot 应用

除了直接使用 java -jar 运行 Spring Boot 应用外,还可以将其作为 systemdinit.d 或 Windows 服务运行。

安装为 systemd 服务

systemd 是 System V init 系统的继承者,现在被许多现代 Linux 发行版使用。 Spring Boot 应用可以通过使用 systemd ‘service’ 脚本来启动。

假设您有一个 Spring Boot 应用打包为 uber jar 在 /var/myapp 中,将其安装为 systemd 服务,创建一个名为 myapp.service 的脚本并将其放在 /etc/systemd/system 目录中。 以下脚本提供了一个示例:

[Unit]
Description=myapp
After=syslog.target network.target

[Service]
User=myapp
Group=myapp

Type=exec
ExecStart=/path/to/java/home/bin/java -jar /var/myapp/myapp.jar
WorkingDirectory=/var/myapp
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

重要提示:请为您的应用程序更改 DescriptionUserGroupExecStartWorkingDirectory 字段。

注意:ExecStart 字段不声明脚本操作命令,这意味着默认使用 run 命令。

应用程序运行用户、PID 文件和控制台日志文件由 systemd 本身管理,因此必须通过 ‘service’ 脚本中的适当字段进行配置。 有关更多详细信息,请参阅 service unit configuration man page

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

$ systemctl enable myapp.service

运行 man systemctl 了解更多详细信息。

安装为 init.d 服务 (System V)

要使用应用程序作为 init.d 服务,请配置其构建以生成 fully executable jar

警告:完全可执行的 jar 通过在文件前面嵌入一个额外脚本来工作。 目前,一些工具不接受这种格式,因此您可能无法始终使用此技术。 例如,jar -xf 可能静默失败以提取完全可执行的 jar 或 war。 建议仅在您打算直接执行它而不是使用 java -jar 或将其部署到 servlet 容器时,才将您的 jar 或 war 完全可执行。

警告:zip64 格式 jar 文件不能完全可执行。 尝试这样做将导致报告为损坏的 jar 文件,当直接执行或使用 java -jar 执行时。 标准格式 jar 文件可以完全可执行,如果它包含一个或多个 zip64 格式嵌套 jar。

要使用 Maven 创建 ‘fully executable’ jar,请使用以下插件配置:

<plugin>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-maven-plugin</artifactId>
	<configuration>
		<executable>true</executable>
	</configuration>
</plugin>

以下示例显示了等效的 Gradle 配置:

tasks.named('bootJar') {
	launchScript()
}

然后可以将其 symlinked 到 init.d 以支持标准 startstoprestartstatus 命令。

默认启动脚本添加到完全可执行的 jar 支持大多数 Linux 发行版,并在 CentOS 和 Ubuntu 上进行了测试。 其他平台,如 OS X 和 FreeBSD,需要使用自定义脚本。 默认脚本支持以下功能:

  • 以 jar 文件的所有者身份启动服务

  • 使用 /var/run/<appname>/<appname>.pid 跟踪应用程序的 PID

  • 将控制台日志写入 /var/log/<appname>.log

假设您有一个 Spring Boot 应用安装在 /var/myapp 中,要安装 Spring Boot 应用作为 init.d 服务,请创建一个符号链接,如下所示:

$ sudo ln -s /var/myapp/myapp.jar /etc/init.d/myapp

安装后,您可以像往常一样启动和停止服务。 例如,在基于 Debian 的系统上,您可以使用以下命令启动它:

$ service myapp start

提示:如果应用程序无法启动,请检查写入 /var/log/<appname>.log 的日志文件中的错误。

您还可以使用标准操作系统工具将应用程序标记为自动启动。 例如,在 Debian 上,您可以使用以下命令:

$ update-rc.d myapp defaults <priority>

保护 init.d 服务

注意:以下是关于如何保护运行作为 init.d 服务的 Spring Boot 应用程序的一些指南。 这不是要列出所有应该做的事情来加强应用程序和它运行的环境。

当作为 root 执行时,默认的可执行脚本运行应用程序作为 RUN_AS_USER 环境变量中指定的用户。 当环境变量未设置时,使用 jar 文件的所有者。 您永远不应该将 Spring Boot 应用程序作为 root 运行,因此 RUN_AS_USER 永远不应为 root,您的应用程序的 jar 文件也不应为 root 所有。 相反,创建一个特定的用户来运行您的应用程序并设置 RUN_AS_USER 环境变量或使用 chown 使其成为 jar 文件的所有者,如下例所示:

$ chown bootapp:bootapp your-app.jar

在这种情况下,默认的可执行脚本运行应用程序作为 bootapp 用户。

提示:为了减少应用程序的用户帐户被破坏的机会,您应该考虑防止它使用登录 shell。 例如,您可以将帐户的 shell 设置为 /usr/sbin/nologin

您还应该采取步骤防止您的应用程序或正在运行的帐户被破坏。 如果攻击者确实获得了访问权限,他们可以将 jar 文件设置为可写并更改其内容。 一种保护方法是将它设置为不可变,使用 chattr,如下例所示:

$ sudo chattr +i your-app.jar

这将防止任何用户(包括 root)修改 jar。

如果 root 用于控制应用程序的服务,并且您 使用 .conf 文件 来定制其启动,则 .conf 文件由 root 用户读取和评估。 它应该被安全地配置。 使用 chmod 使文件只能由所有者读取,并使用 chown 使 root 成为所有者,如下例所示:

$ chmod 400 your-app.conf
$ sudo chown root:root your-app.conf

自定义启动脚本

默认嵌入启动脚本由 Maven 或 Gradle 插件编写,可以以多种方式自定义。 对于大多数人来说,使用默认脚本以及一些自定义通常就足够了。 如果您发现您无法自定义某些需要自定义的内容,请使用 embeddedLaunchScript 选项完全编写自己的文件。

自定义启动脚本当它被写入时

通常在将脚本写入 jar 文件时自定义脚本元素是有意义的。 例如,init.d 脚本可以提供 “description”。 由于您知道描述在前面(并且不需要更改),因此您可以在生成 jar 时提供它。

要自定义写入元素,请使用 Spring Boot Maven 插件的 embeddedLaunchScriptProperties 选项或 properties 属性 的 Spring Boot Gradle 插件的 launchScript

默认脚本支持以下属性替换:

Name Description Gradle default Maven default

mode

脚本模式。

auto

auto

initInfoProvides

“INIT INFO” 的 Provides 部分

${task.baseName}

${project.artifactId}

initInfoRequiredStart

“INIT INFO” 的 Required-Start 部分。

$remote_fs $syslog $network

$remote_fs $syslog $network

initInfoRequiredStop

“INIT INFO” 的 Required-Stop 部分。

$remote_fs $syslog $network

$remote_fs $syslog $network

initInfoDefaultStart

“INIT INFO” 的 Default-Start 部分。

2 3 4 5

2 3 4 5

initInfoDefaultStop

“INIT INFO” 的 Default-Stop 部分。

0 1 6

0 1 6

initInfoShortDescription

“INIT INFO” 的 Short-Description 部分。

单行版本 ${project.description}(如果失败则回退到 ${task.baseName})

${project.name}

initInfoDescription

“INIT INFO” 的 Description 部分。

${project.description}(如果失败则回退到 ${task.baseName})

${project.description}(如果失败则回退到 ${project.name})

initInfoChkconfig

“INIT INFO” 的 chkconfig 部分

2345 99 01

2345 99 01

confFolder

默认值为 CONF_FOLDER

包含 jar 的文件夹

包含 jar 的文件夹

inlinedConfScript

引用应嵌入默认启动脚本中的文件脚本。 这可以用于在加载任何外部配置文件之前设置环境变量,例如 JAVA_OPTS

logFolder

默认值为 LOG_FOLDER。 仅对 init.d 服务有效

logFilename

默认值为 LOG_FILENAME。 仅对 init.d 服务有效

pidFolder

默认值为 PID_FOLDER。 仅对 init.d 服务有效

pidFilename

默认值为 PID_FOLDER 中的 PID 文件名。 仅对 init.d 服务有效

useStartStopDaemon

是否应使用 start-stop-daemon 命令,当它可用时

true

true

stopWaitTime

默认值为 STOP_WAIT_TIME 以秒为单位。 仅对 init.d 服务有效

60

60

自定义脚本当它运行时

对于脚本中需要自定义的项目,您可以使用环境变量或 config file

以下环境属性支持默认脚本:

Variable Description

MODE

操作 “mode”。 默认取决于 jar 的构建方式,但通常是 auto(意味着它尝试猜测它是否是 init 脚本,方法是检查是否是符号链接在名为 init.d 的目录中)。 您可以显式设置为 service,以便 stop|start|status|restart 命令起作用,或设置为 run 如果您想在前台运行脚本。

RUN_AS_USER

将用于运行应用程序的用户。 当未设置时,使用 jar 文件的所有者。

USE_START_STOP_DAEMON

是否应使用 start-stop-daemon 命令,当它可用时。 默认为 true

PID_FOLDER

PID_FOLDER 的根名(默认 /var/run)。

LOG_FOLDER

要放置日志文件的文件夹名(默认 /var/log)。

CONF_FOLDER

要读取 .conf 文件的文件夹名(默认与 jar 文件相同)。

LOG_FILENAME

LOG_FOLDER 中的日志文件名(默认 <appname>.log)。

APP_NAME

应用程序的名称。 如果从符号链接运行 jar,脚本会猜测应用程序名称。 如果它不是符号链接或您想明确设置应用程序名称,这很有用。

RUN_ARGS

传递给程序(Spring Boot 应用程序)的参数。

JAVA_HOME

使用 PATH 默认情况下发现的 java 可执行文件的位置,但您可以显式设置它,如果 $JAVA_HOME/bin/java 中有可执行文件。

JAVA_OPTS

传递给 JVM 的选项,当它启动时。

JARFILE

如果脚本正在用于启动 jar,则 jar 的显式位置,以防脚本实际上不是嵌入的。

DEBUG

如果非空,设置 shell 进程上的 -x 标志,允许您查看脚本中的逻辑。

STOP_WAIT_TIME

停止应用程序之前等待的时间(默认 60 秒)。

注意:PID_FOLDERLOG_FOLDERLOG_FILENAME 变量仅对 init.d 服务有效。 对于 systemd,等效的自定义是通过使用 ‘service’ 脚本完成的。 有关更多详细信息,请参阅 service unit configuration man page

使用 conf 文件

除了 JARFILEAPP_NAME 之外,前面部分中列出的设置可以通过使用 .conf 文件来配置。 该文件应与 jar 文件同名但后缀为 .conf 而不是 .jar,如下例所示:

myapp.conf
JAVA_OPTS=-Xmx1024M
LOG_FOLDER=/custom/log/folder

提示:如果您不喜欢将配置文件与 jar 文件放在一起,您可以设置 CONF_FOLDER 环境变量来自定义配置文件的位置。

要了解如何安全地保护此文件,请参阅 init.d 服务的保护指南

Microsoft Windows 服务

Spring Boot 应用程序可以通过使用 winsw 作为 Windows 服务启动。

一个 (separately maintained sample) 描述了分步如何为您的 Spring Boot 应用程序创建 Windows 服务。