安裝 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 服務。