安装 Spring Boot 应用程序
除了使用 java -jar
直接运行 Spring Boot 应用程序外,还可以将它们作为 systemd
、init.d
或 Windows 服务运行。
作为 systemd 服务安装
systemd
是 System V init 系统的继任者,现在被许多现代 Linux 发行版使用。Spring Boot 应用程序可以使用 systemd
的“服务”脚本启动。
假设您有一个打包为 uber jar 的 Spring Boot 应用程序,位于 /var/myapp
中,要将其作为 systemd
服务安装,请创建一个名为 myapp.service
的脚本,并将其放置在 /etc/systemd/system
目录中。以下脚本提供了一个示例
[Unit]
Description=myapp
After=syslog.target network.target
[Service]
User=myapp
Group=myapp
Environment="JAVA_HOME=/path/to/java/home"
ExecStart=${JAVA_HOME}/bin/java -jar /var/myapp/myapp.jar
ExecStop=/bin/kill -15 $MAINPID
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
请记住为您的应用程序更改 Description 、User 、Group 、Environment 和 ExecStart 字段。
|
ExecStart 字段不声明脚本操作命令,这意味着默认情况下使用 run 命令。
|
运行应用程序的用户、PID 文件和控制台日志文件由 systemd
本身管理,因此必须使用“服务”脚本中的适当字段进行配置。有关更多详细信息,请参阅 服务单元配置手册页。
要将应用程序标记为在系统启动时自动启动,请使用以下命令
$ 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 文件无法设为完全可执行。尝试这样做会导致 jar 文件在直接执行或使用 java -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
以支持标准的 start
、stop
、restart
和 status
命令。
添加到完全可执行 jar 的默认启动脚本支持大多数 Linux 发行版,并在 CentOS 和 Ubuntu 上进行了测试。其他平台(如 OS X 和 FreeBSD)需要使用自定义脚本。默认脚本支持以下功能
-
以拥有 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
如果您的应用程序无法启动,请检查写入 /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 脚本可以提供“描述”。由于您事先知道描述(并且它不需要更改),因此您不妨在生成 jar 文件时提供它。
要自定义已写入的元素,请使用 Spring Boot Maven 插件的 embeddedLaunchScriptProperties
选项或 Spring Boot Gradle 插件的 launchScript
的 properties
属性。
默认脚本支持以下属性替换
名称 | 描述 | Gradle 默认值 | Maven 默认值 |
---|---|---|---|
|
脚本模式。 |
|
|
|
“INIT INFO” 的 |
|
|
|
“INIT INFO” 的 |
|
|
|
“INIT INFO” 的 |
|
|
|
“INIT INFO” 的 |
|
|
|
“INIT INFO” 的 |
|
|
|
“INIT INFO” 的 |
|
|
|
“INIT INFO” 的 |
|
|
|
“INIT INFO” 的 |
|
|
|
|
包含 jar 文件的文件夹 |
包含 jar 文件的文件夹 |
|
对应该在默认启动脚本中内联的文件脚本的引用。这可用于在加载任何外部配置文件之前设置环境变量,例如 |
||
|
|
||
|
|
||
|
|
||
|
|
||
|
当 |
|
|
|
|
60 |
60 |
运行时自定义脚本
对于需要在 jar 文件写入之后自定义的脚本项,可以使用环境变量或 配置文件。
以下环境属性在默认脚本中受支持
变量 | 描述 |
---|---|
|
操作的“模式”。默认值取决于 jar 文件的构建方式,但通常为 |
|
将用于运行应用程序的用户。如果未设置,将使用拥有 jar 文件的用户。 |
|
当 |
|
pid 文件夹的根名称(默认情况下为 |
|
放置日志文件的文件夹的名称(默认情况下为 |
|
读取 .conf 文件的文件夹名称(默认情况下与 jar 文件相同的文件夹)。 |
|
|
|
应用程序的名称。如果 jar 文件从符号链接运行,脚本会猜测应用程序名称。如果它不是符号链接,或者您想显式设置应用程序名称,这将很有用。 |
|
传递给程序(Spring Boot 应用程序)的参数。 |
|
默认情况下, |
|
启动 JVM 时传递给 JVM 的选项。 |
|
jar 文件的显式位置,以防脚本用于启动它未实际嵌入的 jar 文件。 |
|
如果非空,则在 shell 进程上设置 |
|
停止应用程序后强制关闭之前等待的时间(以秒为单位)(默认情况下为 |
PID_FOLDER 、LOG_FOLDER 和 LOG_FILENAME 变量仅对 init.d 服务有效。对于 systemd ,等效的自定义是通过使用“service”脚本进行的。有关更多详细信息,请参阅 服务单元配置手册页。
|
使用配置文件
除了 JARFILE
和 APP_NAME
之外,上一节中列出的设置可以通过使用 .conf
文件进行配置。该文件预计位于 jar 文件旁边,并具有相同的名称,但后缀为 .conf
而不是 .jar
。例如,名为 /var/myapp/myapp.jar
的 jar 文件使用名为 /var/myapp/myapp.conf
的配置文件,如下例所示
JAVA_OPTS=-Xmx1024M
LOG_FOLDER=/custom/log/folder
如果您不喜欢将配置文件放在 jar 文件旁边,您可以设置 CONF_FOLDER 环境变量来自定义配置文件的位置。
|
要了解如何适当地保护此文件,请参阅 有关保护 init.d 服务的指南。