# 安装Spring Boot应用作为系统服务

2021年4月6日发布📑

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

bootJar {
launchScript()
}

#### 2. Unix/Linux 服务

Spring Boot 应用可以容易地作为 Unix/Linux service 让 init.dsystemd 去启动。

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

• 以 jar 文件拥有者的用户去启动服务
• 通过使用 /var/run/<appname>/<appname>.pid 追踪应用程序的 PID
• 将控制台输出的日志写到 /var/log/<appname>.log

$sudo ln -s /var/myapp/myapp.jar /etc/init.d/myapp 一旦安装完成，你就可以按照常规方式去启动和停止服务了。例如，在基于 Debian 的系统，你可以用以下命令启动：$ service myapp start

$update-rc.d myapp defaults <priority> ###### 保护 init.d 服务 ❕ 以下是一些关于以 init.d service 方式运行 Spring Boot 应用需要注意的一些安全问题。 当以 root 执行，即用 root 用户去启动 init.d 的 service，默认的可执行脚本会以环境变量 RUN_AS_USER 所指定的用户去运行应用。当环境变量没有设置，就会以 jar 文件的拥有者用户去执行。你绝不应该以 root 用户运行 Spring Boot 应用，即 RUN_AS_USER 绝不应该设为 root，且你的应用的 jar 文件的拥有者不应该是 root。适当的做法是创建一个专门的用户用于运行应用，并设置 RUN_AS_USER 环境变量的值为该用户，或者使用 chown 去将其设为 jar 文件的拥有者，如以下命令所示：$ chown bootapp:bootapp your-app.jar

$chmod 500 your-app.jar 接下来，限制当帐户被黑了的破坏范围。如果被黑了，黑客可以将 jar 文件设为可写的并修改它的内容。其中一种防护方式是将它设置为不可修改的，通过使用 chattr 命令，命令如下：$ sudo chattr +i your-app.jar

$chmod 400 your-app.conf$ sudo chown root:root your-app.conf
##### 2.2. 安装为一个 systemd Service

systemd 是 System V init system 的继任者，并已被很多现代 Linux 发行版采用。尽管你可以继续在 systemd 使用 init.d 脚本，它也可以使用 systemd ‘service’ 脚本去启动 Spring Boot 应用程序的。

[Unit]
Description=myapp
After=syslog.target

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

[Install]
WantedBy=multi-user.target

❗ 记得修改 Description, UserExecStart 字段为自己的应用程序。

❕ 那个 ExecStart 字段没有声明脚本的动作命令，这意味着默认使用 run 命令

$systemctl enable myapp.service 详情可参考 man systemctl ##### 2.3. 自定义启动脚本 由 Maven 或 Gradle 插件写的内置启动脚本有好几种自定义的方式。对于大多数人而言，使用默认脚本和添加一些新的自定义配置通常就够了。如果发现没法自定义某些需要的东西，那使用 embeddedLaunchScript 选项去写你自己的版本。 ###### 在写入过程自定义启动脚本 通常在启动脚本被写入到 jar 文件的过程时去自定义脚本的元素是合理的。例如, init.d 脚本可以提供一个 “description”. 因为你提前就知道了 description (而且不需要变更),你可能也会在 jar 生成时候提供它。 要自定义写入的元素,使用Spring Boot Maven 插件的 embeddedLaunchScriptProperties 选项, 或 Spring Boot Gradle 插件的 launchScriptproperpies 属性. 默认脚本支持替换的属性如下: 名称 描述 Gradle 默认值 Maven 默认值 mode The script mode. auto auto initInfoProvides The Provides section of “INIT INFO”${task.baseName} ${project.artifactId} initInfoRequiredStart Required-Start section of “INIT INFO”.$remote_fs $syslog$network $remote_fs$syslog $network initInfoRequiredStop Required-Stop section of “INIT INFO”.$remote_fs $syslog$network $remote_fs$syslog $network initInfoDefaultStart Default-Start section of “INIT INFO”. 2 3 4 5 2 3 4 5 initInfoDefaultStop Default-Stop section of “INIT INFO”. 0 1 6 0 1 6 initInfoShortDescription Short-Description section of “INIT INFO”. Single-line version of${project.description} (falling back to ${task.baseName})${project.name}
initInfoDescription Description section of “INIT INFO”. ${project.description} (falling back to${task.baseName}) ${project.description} (falling back to${project.name})
initInfoChkconfig chkconfig section of “INIT INFO” 2345 99 01 2345 99 01
confFolder The default value for CONF_FOLDER Folder containing the jar Folder containing the jar
inlinedConfScript Reference to a file script that should be inlined in the default launch script. This can be used to set environmental variables such as JAVA_OPTS before any external config files are loaded
logFolder Default value for LOG_FOLDER. Only valid for an init.d service
logFilename Default value for LOG_FILENAME. Only valid for an init.d service
pidFolder Default value for PID_FOLDER. Only valid for an init.d service
pidFilename Default value for the name of the PID file in PID_FOLDER. Only valid for an init.d service
useStartStopDaemon Whether the start-stop-daemon command, when it’s available, should be used to control the process true true
stopWaitTime Default value for STOP_WAIT_TIME in seconds. Only valid for an init.d service 60 60
###### 运行时自定义脚本

MODE The “mode” of operation. The default depends on the way the jar was built but is usually auto (meaning it tries to guess if it is an init script by checking if it is a symlink in a directory called init.d). You can explicitly set it to service so that the stop|start|status|restart commands work or to run if you want to run the script in the foreground.
RUN_AS_USER The user that will be used to run the application. When not set, the user that owns the jar file will be used.
USE_START_STOP_DAEMON Whether the start-stop-daemon command, when it’s available, should be used to control the process. Defaults to true.
PID_FOLDER The root name of the pid folder (/var/run by default).
LOG_FOLDER The name of the folder in which to put log files (/var/log by default).
CONF_FOLDER The name of the folder from which to read .conf files (same folder as jar-file by default).
LOG_FILENAME The name of the log file in the LOG_FOLDER (<appname>.log by default).
APP_NAME The name of the app. If the jar is run from a symlink, the script guesses the app name. If it is not a symlink or you want to explicitly set the app name, this can be useful.
RUN_ARGS The arguments to pass to the program (the Spring Boot app).
JAVA_HOME The location of the java executable is discovered by using the PATH by default, but you can set it explicitly if there is an executable file at \$JAVA_HOME/bin/java.
JAVA_OPTS Options that are passed to the JVM when it is launched.
JARFILE The explicit location of the jar file, in case the script is being used to launch a jar that it is not actually embedded.
DEBUG If not empty, sets the -x flag on the shell process, allowing you to see the logic in the script.
STOP_WAIT_TIME The time in seconds to wait when stopping the application before forcing a shutdown (60 by default).

❕ 其中 PID_FOLDER, LOG_FOLDER, 和LOG_FILENAME 变量仅适用于 init.d service. 对于systemd, 等价的自定义设置通过 ‘service’ script 实现. 详情请查看 service unit configuration man page.

myapp.conf

JAVA_OPTS=-Xmx1024M
LOG_FOLDER=/custom/log/folder

💡 如果你不喜欢将config 文件跟 jar 文件放到一起, 你可以设置一个 CONF_FOLDER 环境变量以自定义配置文件的位置.