64. 安装 Spring Boot 应用程序

除了使用java -jar运行 Spring Boot 应用程序外,还可以为 Unix 系统制作完全可执行的应用程序。完全可执行的 jar 可以像其他任何可执行二进制文件一样执行,也可以是在 init.d 或 systemd 中注册。这使得在普通生产环境中安装和 Management Spring Boot 应用程序变得非常容易。

Warning

完全可执行的 jar 通过在文件的开头嵌入一个额外的脚本来工作。当前,某些工具不接受此格式,因此您可能无法始终使用此技术。例如,jar -xf可能会默默地提取无法完全执行的 jar 或 war。建议仅在打算直接执行 jar 或 war 时才使它们完全可执行,而不是使用java -jar运行它或将其部署到 servlet 容器中。

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

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

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

bootJar {
	launchScript()
}

然后,您可以通过键入./my-application.jar(其中my-application是工件的名称)来运行您的应用程序。包含 jar 的目录用作应用程序的工作目录。

64.1 支持的 os

默认脚本支持大多数 Linux 发行版,并已在 CentOS 和 Ubuntu 上进行了测试。其他平台,例如 OS X 和 FreeBSD,则需要使用自定义的embeddedLaunchScript

64.2 Unix/Linux 服务

使用init.dsystemd可以轻松地将 Spring Boot 应用程序作为 Unix/Linux 服务启动。

64.2.1 作为 init.d 服务安装(系统 V)

如果您将 Spring Boot 的 Maven 或 Gradle 插件配置为生成完全可执行的 jar,而不使用自定义embeddedLaunchScript,则您的应用程序可以用作init.d服务。为此,请将 jar 链接到init.d以支持标准startstoprestartstatus命令。

该脚本支持以下功能:

  • 以拥有 jar 文件的用户身份启动服务

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

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

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

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

安装后,您可以按照通常的方式启动和停止服务。例如,在基于 Debian 的系统上,可以使用以下命令启动它:

$ service myapp start

Tip

如果您的应用程序无法启动,请检查写入/var/log/<appname>.log的日志文件是否有错误。

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

$ update-rc.d myapp defaults <priority>

保护 init.d 服务

Note

以下是一组有关如何保护作为 init.d 服务运行的 Spring Boot 应用程序的准则。它并不旨在详尽列出增强应用程序及其运行环境所需的所有工作。

当以 root 身份执行时(例如使用 root 来启动 init.d 服务时),默认的可执行脚本以拥有 jar 文件的用户身份运行应用程序。您永远不要以root的身份运行 Spring Boot 应用程序,因此您的应用程序的 jar 文件绝对不应由 root 拥有。而是创建一个特定用户来运行您的应用程序,并使用chown使其成为 jar 文件的所有者,如以下示例所示:

$ chown bootapp:bootapp your-app.jar

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

Tip

为了减少应用程序的用户帐户遭到破坏的机会,应考虑阻止它使用登录 Shell 程序。例如,您可以将帐户的 Shell 设置为/usr/sbin/nologin

您还应该采取步骤来防止修改应用程序的 jar 文件。首先,配置其权限,使其不能被写入,只能由其所有者读取或执行,如以下示例所示:

$ chmod 500 your-app.jar

其次,如果您的应用程序或运行该应用程序的帐户受到威胁,您还应采取措施限制损害。如果攻击者确实获得了访问权限,则他们可以使 jar 文件可写并更改其内容。防止这种情况发生的一种方法是使用chattr使其不变,如以下示例所示:

$ sudo chattr +i your-app.jar

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

如果使用 root 来控制应用程序的服务,并且您使用.conf 文件自定义其启动,则 root 用户将读取并评估.conf文件。应该相应地对其进行保护。使用chmod,以便只有所有者可以读取文件,并使用chown将 root 成为所有者,如以下示例所示:

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

64.2.2 作为系统服务安装

systemd是 System V init 系统的后继产品,现已被许多现代 Linux 发行版使用。尽管您可以 continue 将_脚本与systemd一起使用,但是也可以通过使用systemd'service'脚本来启动 Spring Boot 应用程序。

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

[Unit]
Description=myapp
After=syslog.target

[Service]
User=myapp
ExecStart=/var/myapp/myapp.jar
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

Tip

切记为您的应用程序更改DescriptionUserExecStart字段。

Note

ExecStart字段未声明脚本操作命令,这意味着默认情况下使用run命令。

请注意,与作为init.d服务运行时不同,运行应用程序,PID 文件和控制台日志文件的用户由systemd本身 Management,因此必须通过在“服务”脚本中使用适当的字段进行配置。有关更多详细信息,请咨询服务单元配置手册页

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

$ systemctl enable myapp.service

有关更多详细信息,请参考man systemctl

64.2.3 自定义启动脚本

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

编写后自定义启动脚本

在将启动脚本写入 jar 文件时,自定义启动脚本的元素通常很有意义。例如,init.d 脚本可以提供“描述”。由于您已经预先了解了描述(并且无需更改),因此在生成 jar 时也可以提供它。

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

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

NameDescriptionGradle defaultMaven default
mode脚本模式。autoauto
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 52 3 4 5
initInfoDefaultStop“ INIT INFO”的Default-Stop部分。0 1 60 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 012345 99 01
confFolderCONF_FOLDER的默认值包含Jar子的文件夹包含Jar子的文件夹
inlinedConfScript引用应在默认启动脚本中内联的文件脚本。可以在加载任何外部配置文件之前设置环境变量,例如JAVA_OPTS
logFolderLOG_FOLDER的默认值。仅对init.d服务有效
logFilenameLOG_FILENAME的默认值。仅对init.d服务有效
pidFolderPID_FOLDER的默认值。仅对init.d服务有效
pidFilenamePID 文件名在PID_FOLDER中的默认值。仅对init.d服务有效
useStartStopDaemonstart-stop-daemon命令(如果可用)是否应用于控制过程truetrue
stopWaitTimeSTOP_WAIT_TIME的默认值,以秒为单位。仅对init.d服务有效6060

运行时自定义脚本

对于编写 jar 之后需要自定义脚本的项目,可以使用环境变量或config file

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

VariableDescription
MODE操作的“模式”。默认值取决于 jar 的构建方式,但通常为auto(这意味着它会通过检查目录init.d中的符号链接来尝试猜测它是否为初始化脚本)。您可以将其显式设置为service,以便stop|start|status|restart命令起作用,或者如果要在前台运行脚本,则可以将其设置为run
USE_START_STOP_DAEMONstart-stop-daemon命令(如果可用)是否应用于控制过程。默认为true
PID_FOLDERpid 文件夹的根名称(默认为/var/run)。
LOG_FOLDER放置日志文件的文件夹的名称(默认为/var/log)。
CONF_FOLDER从中读取.conf 文件的文件夹的名称(默认情况下与 jar 文件相同的文件夹)。
LOG_FILENAMELOG_FOLDER(默认为<appname>.log)中的日志文件名称。
APP_NAME应用程序的名称。如果 jar 是从符号链接运行的,则脚本会猜测该应用程序的名称。如果它不是符号链接,或者您要显式设置应用程序名称,则这将很有用。
RUN_ARGS传递给程序的参数(Spring Boot 应用程序)。
JAVA_HOME默认情况下,通过使用PATH发现java可执行文件的位置,但是如果$JAVA_HOME/bin/java处有可执行文件,则可以显式设置它。
JAVA_OPTS启动 JVM 时传递给 JVM 的选项。
JARFILEjar 文件的显式位置,以防脚本用于启动实际上未嵌入的 jar。
DEBUG如果不为空,请在 shell 进程中设置-x标志,从而易于查看脚本中的逻辑。
STOP_WAIT_TIME停止应用程序之前要强制关闭的 await 时间(以秒为单位)(默认为60)。

Note

PID_FOLDERLOG_FOLDERLOG_FILENAME变量仅对init.d服务有效。对于systemd,使用'service'脚本进行等效的自定义。有关更多详细信息,请参见服务单元配置手册页

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

Tip

如果您不喜欢将配置文件放在 jar 文件旁边,则可以设置CONF_FOLDER环境变量以自定义配置文件的位置。

要了解有关适当保护此文件的信息,请参阅确保 init.d 服务的准则

64.3 Microsoft Windows 服务

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

(单独维护的 samples)分步说明了如何为 Spring Boot 应用程序创建 Windows 服务。