(題外話: 其實(shí)我也是剛學(xué)怎么編寫shell腳本,可能寫得有不好的地方,多多見諒)
平時(shí)我們編寫完java程序后,運(yùn)行調(diào)試都是ide幫我們弄好的,但是實(shí)際情況肯定不會(huì)用ide運(yùn)行,而是打包成jar,用命令行執(zhí)行命令來運(yùn)行程序,所以本著項(xiàng)目部署的方便,我就寫了個(gè)shell腳本.
首先,來解釋下這個(gè)shell腳本需要用到的知識(shí):
首先是這行代碼#!/bin/sh
這行代碼表示這個(gè)腳本使用/bin/sh這個(gè)目錄下的解釋器來執(zhí)行,即這個(gè)腳本就是我們常見的.sh腳本了
JAVAHOME=$JAVA_HOME
初始化jdk的環(huán)境變量,這需要linux系統(tǒng)配置好java環(huán)境
RUNNING_USER=$USER
跟上面一樣,這個(gè)也是初始化執(zhí)行該腳本的用戶變量的,方便我們下面用shell執(zhí)行控制臺(tái)命令
BASEPATH=$(cd
dirname $0
; pwd)
獲取項(xiàng)目根目錄的絕對(duì)路徑,防止項(xiàng)目遷移后又需要修改這個(gè)shell腳本
除了以上幾行代碼之外,其他函數(shù)我都寫了注釋,腳本比較簡(jiǎn)單,大家看注釋就能明白了
#!/bin/sh
# radius server 運(yùn)行腳本
# jdk路徑
JAVAHOME=$JAVA_HOME
# 運(yùn)行程序的用戶
RUNNING_USER=$USER
# 項(xiàng)目根目錄的絕對(duì)地址
BASEPATH=$(cd `dirname $0`; pwd)
# 程序路徑,項(xiàng)目是用maven編譯打包的,所以jar在target文件夾中,絕對(duì)路徑在執(zhí)行時(shí)構(gòu)建,方便項(xiàng)目遷移
APP_HOME=$BASEPATH/target/radiusServer-1.0-SNAPSHOT-jar-with-dependencies.jar
# main方法類
MAIN_CLASS=your.main.class
#構(gòu)建完整的classpath,除了main_class外,還需包含程序運(yùn)行必須的依賴包
#因?yàn)轫?xiàng)目是用maven打包的,所以依賴包會(huì)打包到target/lib目錄下
CLASSPATH=$APP_HOME/classes
for i in $APP_HOME/lib/*.jar; do
CLASSPATH="$CLASSPATH":"$i"
done
################################################################
# 判斷程序是否已經(jīng)啟動(dòng),若已啟動(dòng),則初始化全局psid(程序的id),方便下面停止程序時(shí)使用.
#
# psid: 全局變量,程序的在系統(tǒng)中的id
# jps: java的一個(gè)命令行工具,用于查找本機(jī)上正在運(yùn)行的java程序及其pid
# grep: 正則表達(dá)式搜索命令
# awk: linux上的分割函數(shù),分割后的結(jié)果中,$0表示整行,$1表示第一個(gè)字段,以此類推
#
################################################################
psid=0
initPsid(){
javaps=`$JAVAHOME/bin/jps -l | grep $APP_HOME`
if [ -n "$javaps" ]; then
psid=`echo $javaps | awk '{ print $1}'`
else
psid=0
fi
}
################################################################
# 啟動(dòng)程序
# 1.首先判斷程序是否已經(jīng)啟動(dòng)
# 2.已啟動(dòng),則提示用戶;未啟動(dòng),則執(zhí)行命令啟動(dòng)程序
# 3.最后輸出啟動(dòng)啟動(dòng)程序的結(jié)果
#
# -ne: not equal
# nohup 其他命令 &: 讓程序在后臺(tái)運(yùn)行的的命令,
# 其中,./program >/dev/null 表示將程序普通的輸出流輸出到dev目錄下null文件中(該文件會(huì)自動(dòng)清空,相當(dāng)于黑洞),
# 2>log.out 表示將程序的異常及錯(cuò)誤日志輸出到/home/log.out這個(gè)文件中
# su - user -c commandline: 以u(píng)ser身份運(yùn)行commandline這句命令
# &? 表示上一句命令或函數(shù)執(zhí)行的結(jié)果
#
################################################################
start(){
initPsid
if [ ! -n "$1" ]; then
echo "沒有指定配置文件,使用默認(rèn)配置文件..."
configPath=$BASEPATH/conf.json
else
echo "使用指定的配置文件: $1"
configPath=$1
fi
if [ $psid -ne 0 ]; then
echo "=================================================="
echo "| server has already started |"
echo "=================================================="
else
echo "starting $MAIN_CLASS ..."
JAVA_CMD="nohup $JAVAHOME/bin/java -jar $APP_HOME -c $configPath ./program >log.out &"
su - $RUNNING_USER -c "$JAVA_CMD"
initPsid
if [ $psid -ne 0 ]; then
echo "start [OK] pid=$psid"
else
echo "start [FAILED], $?"
fi
fi
}
################################################################
#
# 停止程序
# 執(zhí)行kill pid來使程序退出
# kill命令默認(rèn)是退出,非強(qiáng)制,服務(wù)端收到退出指令后將執(zhí)行停止操作(如關(guān)閉線程池之類的),
# 執(zhí)行完才算真正退出
#
################################################################
stop(){
initPsid
if [ $psid -ne 0 ]; then
echo -n "Stopping $MAIN_CLASS pid=$psid ..."
su - $RUNNING_USER -c "kill $psid"
if [ $? -eq 0 ]; then
echo "Stop [OK]"
else
echo "Stop [FAILED]"
fi
else
echo "=================================================="
echo "| WARN: $MAIN_CLASS is not running! |"
echo "=================================================="
fi
}
#################################################################
#
# 獲取服務(wù)端程序是否正在運(yùn)行
#
#################################################################
status(){
initPsid
if [ $psid -ne 0 ]; then
echo "Running"
else
echo "not Running"
fi
}
##################################################################
#
# 輸出程序運(yùn)行的環(huán)境
#
##################################################################
info(){
echo "********* System Information ***********"
echo `head -n 1 /etc/issue`
echo `uname -a`
echo
echo "JAVAHOME=$JAVAHOME"
echo `$JAVAHOME/bin/java -version`
echo
echo "USER=$RUNNING_USER"
echo "BASEPATH=$BASEPATH"
echo "APP_HOME=$APP_HOME"
echo "MAIN_CLASS=$MAIN_CLASS"
echo "*****************************************"
}
#################################################################
#
# 根據(jù)參數(shù)確定調(diào)用哪個(gè)函數(shù)
#
# 函數(shù)傳遞參數(shù)的方式: funcName param1 param2
# 在函數(shù)中獲取參數(shù)的方式: $1 $2,第一個(gè)參數(shù)就是$1,第n個(gè)就是$n
#
#################################################################
case "$1" in
'start')
start $2
;;
'stop')
stop
;;
'restart')
stop
start $2
;;
'status')
status
;;
'info')
info
;;
*)
echo "Usage $0 { start | stop | status | restart | info }"
exit
esac
exit 0