現(xiàn)在JAVA Web開發(fā)一般都是用Springboot框架,部署應(yīng)用時(shí)使用Jar包(Java ARchive),也就是Java歸檔文件,而不是使用War包(打包格式的Java web工程)。
War包結(jié)構(gòu)
Jar包和War包的主要區(qū)別就在于Jar包內(nèi)部已經(jīng)集成了Tomcat服務(wù)器,War包部署還需要先安裝一個(gè)Tomcat服務(wù)。用jar部署java服務(wù)更加方便,也是大勢(shì)所趨。在linux服務(wù)器上部署完Jar包程序以后,該如何啟動(dòng)服務(wù)和停止服務(wù)呢?
Jar包的啟動(dòng)
在主機(jī)上先配置好Java的環(huán)境變量,之后就可以用java命令啟動(dòng)Jar包:
java -jar xxx.jar
在啟動(dòng)jar包的時(shí)候,通常需要設(shè)置很多與內(nèi)存有關(guān)的參數(shù),要詳細(xì)了解Java啟動(dòng)內(nèi)存參數(shù),可以閱讀前文《Java面試常見問(wèn)題:JVM內(nèi)存異常及內(nèi)存參數(shù)設(shè)置》。常用的內(nèi)存配置參數(shù)包括:
- -XX: MetapaceSize 設(shè)置元空間大小的初始值;
- -XX:MaxMetaspaceSize 設(shè)置元空間大小的最大值;
- -Xms 設(shè)置堆內(nèi)存的初始值;
- -Xmx 設(shè)置堆內(nèi)存的最大值;
- -Xmn 設(shè)置新生代的大小;
- -Xss 設(shè)置棧區(qū)的大小;
- -XX:SurvivorRatio 設(shè)置新生代中Eden區(qū)域和Survivor區(qū)域的比例,默認(rèn)為8
- -XX:+UseConcMarkSweepGC 設(shè)置垃圾回收器為并發(fā)標(biāo)記清除(Concurrent Mark Sweep)垃圾回收器。
這樣在Jar包的啟動(dòng)命令中要把所有參數(shù)都配置好,可要寫不少字。
java -jar -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -Xms1024m -Xmx1024m -Xmn256m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC xxxService.jar
為了避免每次啟動(dòng)都打這么多字,我們可以把這一長(zhǎng)串啟動(dòng)命令放在Shell腳本中運(yùn)行。要啟動(dòng)Jar包服務(wù)只需要運(yùn)行腳本就行。
Jar包啟動(dòng)腳本
Shell 是一個(gè)用 C 語(yǔ)言編寫的程序,它是用戶使用 Linux/Unix系統(tǒng)的橋梁,有好多種不同版本的Shell。Ken Thompson 開發(fā)的 sh Shell是第一個(gè) Unix Shell。
美國(guó)計(jì)算機(jī)科學(xué)學(xué)者Kenneth Lane Thompson,1983年圖靈獎(jiǎng)得主,C語(yǔ)言前身B語(yǔ)言的作者,Unix發(fā)明人之一
在Linux上,最常用的Shell程序就是 bash。bash保持了對(duì) sh Shell 的兼容性,是各種 Linux 發(fā)行版默認(rèn)配置的 shell。下面我們就看一下如何用shell腳本實(shí)現(xiàn)Jar包啟動(dòng)。
#!/bin/sh
AppDIR=`pwd`
PIDFILE=$APPDIR/xxxService.pid
if [ -f "$PIDFILE" ] && kill -0 $(cat "$PIDFILE"); then
echo "xxxService is already running..."
exit 1
fi
nohup java -jar -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -Xms1024m -Xmx1024m -Xmn256m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC xxxService.jar > out.file 2>&1 & echo $! > $PIDFILE
echo "start xxxService success..."
第一行腳本是說(shuō)明shell程序所在的位置,基本上Linux系統(tǒng)都是一樣的。
第二行腳本是用pwd指令獲取當(dāng)前路徑。通常我們把這個(gè)shell腳本和Jar包文件會(huì)放在一個(gè)路徑下,要特別注意pwd上面的不是單引號(hào),而是鍵盤左上角的“點(diǎn)號(hào)”。APPDIR就是腳本所在的當(dāng)前路徑了。
第三行腳本定義了變量PIDFILE,指向文件名xxxService.pid,這個(gè)文件就是用來(lái)記錄Jar包啟動(dòng)后的進(jìn)程ID。這樣將來(lái)就可以用進(jìn)程ID來(lái)關(guān)閉Jar包服務(wù)了。
第四行腳本是判斷是否xxxService程序已經(jīng)運(yùn)行了。
- [-f "$PIDFILE"]是查詢pid文件是否存在。
- cat "$PIDFILE"是打印pid文件內(nèi)容,也就是進(jìn)程ID。
- kill -0 pid的意思并不是要?dú)⑺肋M(jìn)程,而是讓系統(tǒng)來(lái)對(duì)進(jìn)程進(jìn)行檢查,如果進(jìn)程不存在,kill -0會(huì)報(bào)錯(cuò)。
第5行到第7行腳本的含義:如果pid文件存在且對(duì)應(yīng)進(jìn)程也存在,那么說(shuō)明Jar包已經(jīng)啟動(dòng)了,不需要再重新啟動(dòng),腳本退出運(yùn)行。
如果Jar包尚未啟動(dòng),則運(yùn)行第8行腳本。省略掉Java啟動(dòng)內(nèi)存設(shè)置參數(shù),就是下面這樣:
nohup java -jar xxxService.jar > out.file 2>&1 & echo $! > $PIDFILE
- nohup 意思是不掛斷運(yùn)行命令,當(dāng)賬戶退出或終端關(guān)閉時(shí),程序仍然運(yùn)行。
- >outfile 代表輸出重定向,程序運(yùn)行時(shí)的標(biāo)準(zhǔn)輸出內(nèi)容都會(huì)打印到out.file上。
- 2>&1 就是將標(biāo)準(zhǔn)錯(cuò)誤重定向到標(biāo)準(zhǔn)輸出。標(biāo)準(zhǔn)輸出已經(jīng)到了out.file上,因此錯(cuò)誤也會(huì)輸出到這個(gè)文件上面。如果不希望記錄標(biāo)準(zhǔn)輸出和錯(cuò)誤,可以重定向到/dev/null上,因?yàn)?/dev/null 是一個(gè)不存在的設(shè)備,從這里什么也讀不出來(lái)。
- &代表在后臺(tái)運(yùn)行,echo $! > $PIDFILE 則是把進(jìn)程ID輸出到pid文件上。
第8行腳本執(zhí)行成功后,第9行腳本打印成功。另外我們還可以在當(dāng)前目錄下發(fā)現(xiàn)多了一個(gè)xxxService.pid文件。
Jar包停止運(yùn)行
那么要如何關(guān)掉正在執(zhí)行的Java進(jìn)程呢,通常可以運(yùn)行:
ps aux | grep xxxService
這句指令會(huì)列出所有帶有xxxService字樣的進(jìn)程,在其中我們找到要關(guān)掉的進(jìn)程ID,隨后就用kill -9 pid可以殺死進(jìn)程。kill -9 發(fā)送SIGKILL信號(hào)給進(jìn)程,告訴進(jìn)程,你被終結(jié)了,請(qǐng)立刻退出。
不過(guò)有了啟動(dòng)腳本作為基礎(chǔ),我們不需要再費(fèi)力去找進(jìn)程ID。結(jié)合啟動(dòng)腳本,我們還可以設(shè)計(jì)下面這樣一個(gè)停止腳本。
#!/bin/sh
APPDIR=`pwd`
PIDFILE=$APPDIR/xxxService.pid
if [ ! -f "$PIDFILE" ] || ! kill -0 "$(cat "$PIDFILE")"; then
echo "xxxService not running..."
else
echo "stopping xxxService..."
PID="$(cat "$PIDFILE")"
kill -9 $PID
rm "$PIDFILE"
echo "...xxxService stopped"
fi
這個(gè)停止腳本和啟動(dòng)腳本類似,這里就不再逐行解釋了,如果大家有什么問(wèn)題,可以在評(píng)論區(qū)留言。