安装 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 服务,请配置其构建以生成一个完全可执行的 jar

完全可执行的 jar 通过在文件前面嵌入一个额外的脚本来实现其功能。目前,有些工具不接受这种格式,因此您可能无法总是使用这种技术。例如,jar -xf 可能会静默地无法提取已完全可执行的 jar 或 war 文件。建议仅在您打算直接执行 jar 或 war 文件,而不是通过 java -jar 运行它或将其部署到 servlet 容器时,才将它们设置为完全可执行。
zip64 格式的 jar 文件无法设置为完全可执行。尝试这样做将导致一个在直接执行或使用 java -jar 时报告损坏的 jar 文件。包含一个或多个 zip64 格式嵌套 jar 的标准格式 jar 文件可以是完全可执行的。

要使用 Maven 创建一个“完全可执行”的 jar,请使用以下插件配置:

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

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

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

然后可以将其符号链接到 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 执行时(例如使用 root 启动 init.d 服务时),默认的可执行脚本会以 RUN_AS_USER 环境变量中指定的用户运行应用程序。当未设置该环境变量时,则使用拥有 jar 文件的用户。您绝不应以 root 用户运行 Spring Boot 应用程序,因此 RUN_AS_USER 绝不应为 root,并且您的应用程序的 jar 文件也绝不应由 root 拥有。相反,请创建一个特定用户来运行您的应用程序,并设置 RUN_AS_USER 环境变量或使用 chown 将其设为 jar 文件的所有者,如下例所示:

$ chown bootapp:bootapp your-app.jar

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

为了减少应用程序用户账户被入侵的可能性,您应该考虑阻止其使用登录 shell。例如,您可以将其账户的 shell 设置为 /usr/sbin/nologin

您还应采取措施防止修改应用程序的 jar 文件。首先,配置其权限,使其不可写,并且只能由其所有者读取或执行,如下例所示:

$ chmod 500 your-app.jar

其次,您还应采取措施限制在您的应用程序或运行它的账户被入侵时造成的损害。如果攻击者确实获得了访问权限,他们可以使 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 选项,或 Spring Boot Gradle 插件 launchScriptproperties 属性

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

名称 描述 Gradle 默认值 Maven 默认值

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

停止应用程序前的等待时间(秒)。仅对 init.d 服务有效

60

60

运行时定制脚本

对于需要在写入 jar 文件后进行定制的脚本项,您可以使用环境变量或配置文件

默认脚本支持以下环境变量:

变量 描述

MODE

操作模式。“模式”取决于构建 jar 的方式,但通常是 auto(这意味着它会尝试通过检查是否是名为 init.d 的目录中的符号链接来猜测是否是 init 脚本)。您可以将其明确设置为 service,以便 stop|start|status|restart 命令工作,或者设置为 run,如果您想在前台运行脚本。

RUN_AS_USER

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

USE_START_STOP_DAEMON

start-stop-daemon 命令可用时,是否应使用它来控制进程。默认为 true

PID_FOLDER

pid 文件夹的根名称(默认为 /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

java 可执行文件的位置默认通过 PATH 发现,但如果 $JAVA_HOME/bin/java 存在可执行文件,您可以明确设置它。

JAVA_OPTS

启动 JVM 时传递给 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。例如,名为 /var/myapp/myapp.jar 的 jar 文件使用名为 /var/myapp/myapp.conf 的配置文件,如下例所示:

myapp.conf
JAVA_OPTS=-Xmx1024M
LOG_FOLDER=/custom/log/folder
如果您不想将配置文件放在 jar 文件旁边,可以设置 CONF_FOLDER 环境变量来定制配置文件的位置。

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

Microsoft Windows 服务

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

一个(单独维护的示例)详细描述了如何为您的 Spring Boot 应用程序创建 Windows 服务。