Linux:啓動、偵錯、停止和重新啓動Java程式的Shell指令碼

2020-08-08 22:14:29

Shell介紹

Shell 教學

Shell 是一個用 C 語言編寫的程式,它是使用者使用 Linux 的橋樑。Shell 既是一種命令語言,又是一種程式設計語言。

Shell 是指一種應用程式,這個應用程式提供了一個介面,使用者通過這個介面存取操作系統內核的服務。

Ken Thompson 的 sh 是第一種 Unix Shell,Windows Explorer 是一個典型的圖形介面 Shell。

Shell 指令碼

Shell 指令碼(shell script),是一種爲 shell 編寫的指令碼程式。

業界所說的 shell 通常都是指 shell 指令碼,但讀者朋友要知道,shell 和 shell script 是兩個不同的概念。

由於習慣的原因,簡潔起見,本文出現的 「shell程式設計」 都是指 shell 指令碼程式設計,不是指開發 shell 自身。

Shell知識點

變數

等號設定變數

變數名=變數內容

$ 讀取,單引號中$ 變數名,雙引號中$ 變數名、$ {變數名}都可

$ 變數名、$ {變數名}

傳遞參數

$ n,n代表第幾個數位
$ 0 爲執行的檔名,其餘代表第n個參數

$ n

運算子

算術運算子

+ 加
- 減
* 乘
/ 初
= 賦值
== 相等
!= 不相等

關係運算符

-eq 相等返回 true
-ne	不相等返回 true
-gt	>返回 true
-lt	<返回 true
-ge	>=返回 true
-le <=返回 true

布爾運算子

!	非運算
-o	或運算
-a	與運算

邏輯運算子

&&	AND
||	OR

字串運算子

=	兩個字串相等返回 true	[ $a = $b ] 
!=	不相等返回 true
-z	字串長度爲0返回 true
-n	字串長度不爲 0 返回 true
$	字串s不爲空返回 true。

命令

echo,輸出字串

echo string

流程控制

if else-if else

if condition1
then
    command1
elif condition2 
then 
    command2
else
    commandN
fi

for 回圈

for var in item1 item2 ... itemN
do
    command1
    command2
    ...
    commandN
done

while 語句

while condition
do
    command
done

switch case

casein
模式1)
    command1
    command2
    ...
    commandN
    ;;
模式2)
    command1
    command2
    ...
    commandN
    ;;
esac

函數

[ function ] funname [()]

{

    action;

    [return int;]

}

參數

$#	傳遞到指令碼或函數的參數個數
$*	以一個單字串顯示所有向指令碼傳遞的參數
$$	指令碼執行的當前進程ID號
$!	後臺執行的最後一個進程的ID號
$@$*相同,但是使用時加引號,並在引號中返回每個參數。
$-	顯示Shell使用的當前選項,與set命令功能相同。
$?	顯示最後命令的退出狀態。0表示沒有錯誤,其他任何值表明有錯誤。

輸入/輸出重定向

command > file	將輸出重定向到 file。
command < file	將輸入重定向到 file。
command >> file	將輸出以追加的方式重定向到 file。

Shell指令碼

windows下編譯的shell檔案,每一行的結尾是\n\r,而在linux下檔案的結尾是\n
檔案放入linux後,用以下命令解決

$ sed -i 's/\r$//' 檔名

註釋版

# export:用於設定或顯示環境變數
# export [-fnp][變數名稱]=[變數設定值]
export JAVA_HOME=/usr/java/jdk1.8.0_11
export JRE_HOME=$JAVA_HOME/jre

# 變數賦值,反斜槓爲跳脫
# API_NAME+JAR_NAME 包名
API_NAME=helloworld
JAR_NAME=$API_NAME\.jar
# 啓動日誌名
LOG_NAME=$API_NAME\.log
#PID  代表是PID檔案
PID=$API_NAME\.pid


# 方法:使用說明,用來提示輸入參數
formatDescription() {
	# echo:輸出字串
	# -e:開啓跳脫
	echo -e "===============Please use the following format==================\n"
 	echo -e ">>>      sh service.sh [start|debug|stop|restart|status]      <<<"
    echo -e "\n==============================================================="
	# exit  0:正常執行程式並退出程式;
	# exit  1:非正常執行導致退出程式;
	exit 1
}

# 方法:檢查程式是否在執行
checkStatus(){
	# ps -ef|grep $JAR_NAME 匹配進程中包名
	# grep -v 參數 : 過濾 匹配參數
	# awk '{print $2}' 匹配第二個參數
	# $0 就是你寫的shell指令碼本身的名字
	# $1 是你給你寫的shell指令碼傳的第一個參數
	# $2 是你給你寫的shell指令碼傳的第二個參數
	pid=`ps -ef|grep $JAR_NAME|grep -v grep|awk '{print $2}' `
	# if then、elif then、else、fi
	# [ -z STRING ]  「STRING」 的長度爲零則爲真
	# 如果不存在返回1,存在返回0     
	if [ -z "${pid}" ]; then
		return 1
	else
		return 0
	fi
}

# 方法:啓動方法
startService(){
	# 呼叫shell內的方法
	checkStatus
	# $?:獲取函數返回值或者上一個命令的退出狀態
	# -eq : 等於
	if [ $? -eq "0" ]; then 
		echo ">>> ${JAR_NAME} is already running, PID=${pid} <<<" 
	else
		# nohup + & :後臺執行
		# >$LOG_NAME : 將日誌資訊輸出到log日誌中
		# 0 表示stdin標準輸入
		# 1 表示stdout標準輸出
		# 2 表示stderr標準錯誤
		# & 相當於等效於標準輸出
		# 2>&1 是將標準錯誤資訊轉變成標準輸出,這樣就可以將錯誤資訊輸出到out.log 日誌裏面來
		# -noverify:關閉位元組碼驗證 
		# java -jar XXX.jar :執行jar
		nohup $JRE_HOME/bin/java -noverify -Xms512m -Xmx1024m -jar $JAR_NAME >$LOG_NAME 2>&1 &
		# $! Shell最後執行的後臺Process的PID
		# '>'  爲建立: echo 「hello shell」  > out.txt
		# '>>' 爲追加:echo 「hello shell」  >> out.txt
		# 將進程的pid輸出到.pid檔案中(PID=$API_NAME\.pid)
		echo $! > $PID
		echo ">>>  ${JAR_NAME} start successfully, PID=$! <<<" 
	fi
}

# 方法:debug方法
debugService(){
  checkStatus
  if [ $? -eq "0" ]; then 
    echo ">>> ${JAR_NAME} is already running, PID=${pid} <<<" 
  else 
    nohup $JRE_HOME/bin/java -agentlib:jdwp=transport=dtSocket,server=y,suspend=n,address=5006 -Xms512m -Xmx1024m -jar $JAR_NAME >$LOG_NAME 2>&1 &
    echo $! > $PID
    echo ">>>  ${JAR_NAME} start in debug mode successfully, PID=$! <<<" 
   fi
}

# 方法:停止方法
stopService(){
  # cat讀取PID檔案
  pidf=$(cat $PID)
  #echo "$pidf"  
  echo ">>> ${JAR_NAME} begin kill, $pidf <<<"
  # kill 殺進程
  kill $pidf
  # rm -rf : 刪除檔案
  rm -rf $PID
  # 休眠3s
  sleep 3
  checkStatus
  if [ $? -eq "0" ]; then 
    echo ">>> kill failed, kill it forcefully <<<"
	echo ">>>  ${JAR_NAME} begin kill -9 $pid <<<"
	# kill -9 強制殺進程
    kill -9  $pid
    sleep 3
	# 無需確認,進程biss
    echo ">>> ${JAR_NAME} has been killed	<<<"  
  else
    echo ">>> ${JAR_NAME} has stopped <<<"
  fi  
}

# 方法:重新啓動
restartService(){
  stopService
  startService
}

# 方法:輸出執行狀態
statusService(){
  checkStatus
  if [ $? -eq "0" ]; then
    echo ">>> ${JAR_NAME} is running, PID=${pid} <<<"
  else
    echo ">>> ${JAR_NAME} is not running <<<"
  fi
}

# 根據輸入參數,選擇執行對應方法,不輸入則執行使用說明
# case expression in
# 	pattern 1)
# 		statement1
# 		;;
# 	pattern 2)
# 		statement2
# 		;;
# ……
# 	*)
# 		statementn
# esac	
case "$1" in
  "start")
    startService
    ;;
  "stop")
    stopService
    ;;
  "status")
    statusService
    ;;
  "restart")
    restartService
    ;;
  "debug")
    debugService
    ;;
  *)
    formatDescription
    ;;
esac
exit 0

純淨版

export JAVA_HOME=/usr/java/jdk1.8.0_11
export JRE_HOME=$JAVA_HOME/jre

API_NAME=helloworld
JAR_NAME=$API_NAME\.jar
LOG_NAME=$API_NAME\.log
PID=$API_NAME\.pid

formatDescription() {
	echo -e "===============Please use the following format==================\n"
 	echo -e ">>>      sh service.sh [start|debug|stop|restart|status]      <<<"
    echo -e "\n==============================================================="
	exit 1
}

checkStatus(){
	pid=`ps -ef|grep $JAR_NAME|grep -v grep|awk '{print $2}' `    
	if [ -z "${pid}" ]; then
		return 1
	else
		return 0
	fi
}

startService(){
	checkStatus
	if [ $? -eq "0" ]; then 
		echo ">>> ${JAR_NAME} is already running, PID=${pid} <<<" 
	else
		nohup $JRE_HOME/bin/java -noverify -Xms512m -Xmx1024m -jar $JAR_NAME >$LOG_NAME 2>&1 &
		echo $! > $PID
		echo ">>>  ${JAR_NAME} start successfully, PID=$! <<<" 
	fi
}

debugService(){
  checkStatus
  if [ $? -eq "0" ]; then 
    echo ">>> ${JAR_NAME} is already running, PID=${pid} <<<" 
  else 
    nohup $JRE_HOME/bin/java -agentlib:jdwp=transport=dtSocket,server=y,suspend=n,address=5006 -Xms512m -Xmx1024m -jar $JAR_NAME >$LOG_NAME 2>&1 &
    echo $! > $PID
    echo ">>>  ${JAR_NAME} start in debug mode successfully, PID=$! <<<" 
   fi
}

stopService(){
  pidf=$(cat $PID)
  echo ">>> ${JAR_NAME} begin kill, $pidf <<<"
  kill $pidf
  rm -rf $PID
  sleep 3
  checkStatus
  if [ $? -eq "0" ]; then 
    echo ">>> kill failed, kill it forcefully <<<"
	echo ">>>  ${JAR_NAME} begin kill -9 $pid <<<"
    kill -9  $pid
    sleep 3
    echo ">>> ${JAR_NAME} has been killed	<<<"  
  else
    echo ">>> ${JAR_NAME} has stopped <<<"
  fi  
}

restartService(){
  stopService
  startService
}

statusService(){
  checkStatus
  if [ $? -eq "0" ]; then
    echo ">>> ${JAR_NAME} is running, PID=${pid} <<<"
  else
    echo ">>> ${JAR_NAME} is not running <<<"
  fi
}

case "$1" in
  "start")
    startService
    ;;
  "stop")
    stopService
    ;;
  "status")
    statusService
    ;;
  "restart")
    restartService
    ;;
  "debug")
    debugService
    ;;
  *)
    formatDescription
    ;;
esac
exit 0