一.引言
在linux系統中,我們通常使用下面指令來部署springboot項目:
nohup java -jar appname.jar --spring.profiles.active=qa > /dev/null 2>&1 & echo $! >"appname.pid"
除了上述使用java -jar的方式部署springboot項目之外,springboot官方文檔還提供了另外一種部署方式:使用init.d
或者systemd的方式部署Springboot項目。
使用這種方式部署項目有什麼好處呢,可以使用SysVinit/Systemd的管理指令,start,stop,restart,status管理springboot項目,還有提供開機自啓的功能,方便在機房停電,或者服務器異常重啓後不用手工執行腳本或指令重啓服務,使Springboot程序真正意義的安裝在linux機器上,作爲守護進程運行。
官方文檔關於linux上的部署,有專門的篇幅來描述,官方文檔鏈接:https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/htmlsingle/#deployment-install
如文檔所述,有init.d以及systemd兩種部署方式。本文只講第一種,以inid.d/System V/SysVinit的方式部署。
二.說明
1.使用這種方式部署springboot項目,實際上是在文件的開頭內嵌了額外的腳本,某些工具可能不支持這種格式。這樣可能會導致你打包好的jar包無法使用java -jar運行,或者打包好的Jar包無法跑在servlet容器上,例如tomcat。所以,只有當你只打算使用init.d、Systemd部署springboot程序時,才使用這種方式來打包。當然,在某些情況下是支持的,不過風險還是很大,筆者在公司實際運行的項目使用了這種方式打包,結果使用java -jar華麗麗的就跑不起來,但是使用本文中的demo springboot項目卻完完全全沒問題。
2.這種內嵌的腳本支持大多數的linux發行版,springboot官方在centos和ubuntu上做了測試。本文在centos7.5測試通過。其他平臺需要使用embeddedLaunchScript。
三.實戰步驟
這裏詳解官方文檔介紹的第一種部署方式:init.d服務(System V)
1.如果你使用maven或者gradle把springboot項目打包成可執行程序,你可以在linux上把它安裝成init.d服務,支持標準的start、stop、restart、status命令。
所以首先,需要藉助maven,把springboot項目打包成爲可執行程序,配置如下
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
如果使用gradle,等效於
bootJar {
launchScript()
}
2.詳細演示:
本文以下述條件在centos7.5的linux機器上做了實驗,所以對情景做以下假設:
(1)部署服務器的目錄爲/data/project/demo
(2)打包後的jar包名稱爲demo-0.0.1-SNAPSHOT.jar
(3)部署的appname爲demo-0.0.1-SNAPSHOT
(4) SpringBoot的版本爲2.2.2.RELEASE,使用Maven打包,理論上與springboot版本無關,只跟maven打包有關係
init.d部署的步驟如下:
第一步,把第1點列出的maven的配置,配置在springboot的pom文件上,然後執行
mvn clean install
上述maven指令將springboot程序打包(打包指令自己決定即可,以上只是一個例子),本文打包生成了一個demo-0.0.1-SNAPSHOT.jar文件,最後將這個打包後的文件demo-0.0.1-SNAPSHOT.jar文件上傳到linux部署服務器上。
上傳可以使用scp指令,也可以藉助xftp等文件傳輸工具,詳見百度。
第二步,登錄服務器,cd /data/project/demo進入文件上傳的目錄,並確保該jar包權限可以執行,
chmod +x /data/project/demo/demo-0.0.1-SNAPSHOT.jar
執行以上命令賦予jar文件執行權限
第三步,設置短鏈接
sudo ln -s /data/project/demo/demo-0.0.1-SNAPSHOT.jar /etc/init.d/demo-0.0.1-SNAPSHOT
第四步,這時候已經安裝好了,啓動服務:
service demo-0.0.1-SNAPSHOT start
第五步,設置開機自動啓動服務:
centos系統使用以下指令設置開機自啓 :
chkconfig demo-0.0.1-SNAPSHOT on
關閉開機自啓指令:
chkconfig demo-0.0.1-SNAPSHOT off
ubuntu系統使用以下指令開機自啓:
update-rc.d demo-0.0.1-SNAPSHOT defaults <priority>
(<priority>是一個優先級,自己設定,沒有使用過ubuntu進行過測試,centos指令筆者在centos7.5執行並驗證成功)
注意:
(1)執行完第三步,springboot程序已經安裝好了,這時候已經可以使用init.d服務的指令start,stop,restart,status管理springboot程序的啓動,停止,重啓,和查看服務的運行狀態,並且使用chkconfig指令管理是否開機自啓
(2)執行第五步時,如果這時候你同時安裝了systemd,會自動轉發使用systemd的enable,如果沒有安裝,則使用chkconfig
(3)如果啓動失敗,請在默認的控制檯輸出文件/var/log/demo-0.0.1-SNAPSHOT.log查看錯誤日誌。
使用這種方式默認的pid和控制檯輸出文件:
(1)pid存放位置: /var/run/<appname>/<appname>.pid
(2)控制檯輸出文件路徑:/var/log/<appname>.log
(3)默認讀取的配置文件爲jar包存放位置的同目錄下的<appname>.conf,這裏爲/data/project/demo/demo-0.0.1-SNAPSHOT.conf,如果需要配置,請自己在該目錄創建demo-0.0.1-SNAPSHOT.conf
3.相關配置
該init.d服務的配置有以下兩種方式,一種是在springboot項目的pom文件裏面配置,一種是在<appname>.conf中配置,支持的所有詳細配置參見官方文檔:https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/htmlsingle/#deployment-install
英文The following property substitutions are supported with the default script下面的兩個表格,第一個表格是maven配置,第二個表格是conf支持的配置。
(1)其中maven配置如下
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
<embeddedLaunchScriptProperties>
<!--控制檯日誌存放的位置,如果配置不存在的目錄,則會輸出到/tmp目錄,
如果想丟棄控制檯日誌,則logFolder設爲/dev,logFilename設爲null-->
<logFolder>/data/project/demo/log</logFolder>
<!--控制檯日誌文件名-->
<logFilename>test.log</logFilename>
<!--pid文件存放的位置,實際上存放的目錄爲/var/run/<appname>,如果目錄不存在,則會到/tmp目錄
會自動創建多一級以項目名命名的目錄
另外,值得注意的一點就是使用service <appname> stop/restart時
會直接讀取這個值,如果直接改變,會導致該指令按照該目錄+項目名和文件名的位置去查找,
找不到pid,導致停止或者重啓失敗,這時候要麼手動執行kill命令,
要麼把原先的pid文件拷貝到新指定的目錄和文件
-->
<pidFolder>/var/run</pidFolder>
<!--pid文件名-->
<pidFilename>demo-0.0.1-SNAPSHOT.pid</pidFilename>
<!--指定配置文件的位置,最終讀取配置文件的位置爲/data/file/<appname>.conf-->
<confFolder>/data/file</confFolder>
<!--還有一個有用的參數爲inlinedConfScript,該參數只接受腳本路徑
,不直接支持腳本內容,這裏沒有去測試-->
</embeddedLaunchScriptProperties>
</configuration>
</plugin>
(2)conf配置
另外還有conf的配置,默認需要配置在jar包的同級目錄下,如果使用maven重新指定,就讀取maven配置的目錄下的<appname>.conf
注意,如果maven的配置與conf的配置衝突,則優先使用conf的配置,兩者的配置是取並集,即合集。
如果使用init.d的方式部署服務,則這個配置一定少不了,因爲使用這種方式部署springboot服務,java的自定義參數只能在這裏定義和配置。如JVM的參數,如Java程序的啓動參數,maven方式並不支持,除非自定義內嵌腳本,這種需要自己寫腳本,在本文中並沒有嘗試。
demo-0.0.1-SNAPSHOT.conf如下配置:
#jvm啓動參數
JAVA_OPTS="-Xmx1024M -Xms1024M"
#springboot java程序啓動參數
RUN_ARGS="--spring.profiles.active=pd"
#pid的存放目錄,同maven配置描述的,實際目錄爲PID_FOLDER/<appname>,不配置默認爲/var/run
PID_FOLDER=/var/run
#控制檯輸出日誌存放目錄,不配置默認爲/var/log,如果想丟棄控制檯文件,請設置爲/dev,LOG_FOLDER設置爲null
LOG_FOLDER=/data/project/demo/log
#控制檯輸出日誌文件名
LOG_FILENAME=demo-0.0.1-SHAPSHOT.log
#java指令的位置,默認使用PATH路徑來發現,也可以顯示指定爲$JAVA_HOME/bin/java,以下直接配置真實路徑
JAVA_HOME=/usr/java/default/bin/java
其他參數詳見官方文檔,以上的配置如果與maven衝突,conf配置優先級最高
關於卸載init.d,其實就是刪除init.d的軟鏈接,如果設置了開機自啓,再執行systemctl daemon-reload重載一下自啓配置
四.寫在最後
在linux系統上執行 vi demo-0.0.1-SNAPSHOT.jar,會發現裏面的內容由shell腳本 + jar包實際內容二進制 組成,如下圖所示
如上圖,exit 0 之後,後面的爲jar包二進制。
因爲文件前內嵌了shell腳本,因此可以使用 sh ./demo-0.0.1-SNAPSHOT.jar來直接執行。
然後神奇的發現,可以使用360壓縮打開,不影響jar包,或許這就是可以繼續使用java -jar執行的原因,大膽的猜測,當不能使用360壓縮打開時,java -jar就無效了,因爲java -xf已經不能提取出來jar/war了
由上面的腳本,不難發現init.d的實現原理其實就是這一小戳精髓的shell腳本內容。由此可以自己實現一個自己的init.d。
以上的所有內容都是經過本人一一測試的,如果內容有誤,歡迎評論,看到會回。