shell_test
專案主要是在阿里雲伺服器上使用指令碼(shell)實現服務列表展示後選擇並操作的功能:比如例子中有四個jar包,啟動指令碼後展示4個服務,編號1-4,選擇對應編號後可以選擇啟動或者停止服務。
專案程式碼獲取:https://github.com/pysasuke/s…
具體步驟如下
1、登入阿里雲伺服器,在某一路徑下新建資料夾test,並進入test路徑,命令如下:
mkdir test
cd test
2、在test資料夾下新建多個java類,命令如下:
vim Service1.java
內容如下:
public class Service1{
public static void main(String[] args){
while(true){
}
}
}
3、編譯java類,得到class檔案,命令如下:
javac Service1.java
4、將class檔案打成jar包,並制定執行的主類,命令如下:
jar cvfe service1.jar Service1 Service1.class
以四個類為例子,得到四個jar檔案service1.jar、service2.jar、service3.jar、service4.jar
5、新建文字文件list.txt,命令如下:
vim list.txt
並寫入下內容:
service1.jar
service2.jar
service3.jar
service4.jar
5、新建start.sh檔案,命令如下:
vim start.sh
內容如下:
#!/bin/bash
# 全域性變數
SERVICES_NUM=0 # 當前服務序號
SERVICES_ARRAY=() # 服務名儲存陣列
SERVICES_EXTENSION=() # 服務字尾儲存陣列
PIDS_ARRAY=() # 服務pid儲存陣列
GREEN_BEGIN=" 33[32m" # 綠色
RED_BEGIN=" 33[31m" # 紅色(用於錯誤提示)
COLOR_END=" 33[0m" # 關閉所有屬性
# 展示服務列表
list_services() {
# (與全域性變數同名)會覆蓋全域性變數的值(如果不想影響需用在變數前加local修飾,標記為區域性變數)
SERVICES_NUM=0
SERVICES_ARRAY=()
PIDS_ARRAY=()
# grep -Ev `^#|^$`` 檔名
# -E是擴充套件的grep,即egrep,使用正規表示式
# -v是反選,除了匹配正則的行都列印出來
# 正則:
# ^# 以#開頭的行
# | 或者
# ^$ 空行
services=`cat list.txt | grep -Ev `^#|^$`` # 讀檔案(按正則篩選:去掉以#開頭的行和空行)
show_heard
for service in ${services}; do
show_list ${service}
done
}
show_heard(){
# 格式: echo -e " 33[字背景顏色;字型顏色m字串 33[0m"
echo ""
echo -e ${GREEN_BEGIN}" 服務編號 服務名 程式代號(PID)"${COLOR_END}
echo -e ${GREEN_BEGIN}" -------- -------------------- -------------"${COLOR_END}
}
show_list(){
service=$1 # 取傳入的第一個引數
name=${service%.*} # %.* 刪除最後一個.及其右邊的字串(刪除.jar字尾)
extension=${service##*.} # ##*. 刪掉最後一個 . 及其左邊的字串
# ps -ef | 全格式顯示當前所有程式
# grep 過濾/搜尋的特定字元
# 轉譯符
# grep -v grep 把``grep``這個程式忽略掉
# awk `{print $2}` $fileName : 一行一行的讀取指定的檔案,以空格作為分隔符,列印第二個欄位(PID)
pid=$(ps -ef | grep "-jar $service$" | grep -v grep | awk `{ print $2 }`) # 獲取指定服務的pid
SERVICES_NUM=$(($SERVICES_NUM+1)) # 自增操作
SERVICES_ARRAY[$SERVICES_NUM]=${name} # 把處理過的模組名字放入陣列
SERVICES_EXTENSION[$SERVICES_NUM]=${extension} # 把字尾放入陣列
PIDS_ARRAY[$SERVICES_NUM]=${pid} # 把pid放入陣列
printf " %8d %-20s %s
" "$SERVICES_NUM" "${name}" "$pid" # 格式化輸出
}
# 等待完成
waiting_for_complete() {
service=$1 # 獲取第一個引數 服務(服務名.字尾)
action=$2 # 獲取第二個引數 操作(啟動:START或者停止:STOP)
while true; do
# 獲取指定服務的pid
pid=$(ps -ef | grep "-jar $service$" | grep -v grep | awk `{ print $2 }`)
if [ ${action} = "START" ]; then # 指令為啟動
if [ -z ${pid} ]; then # 如果pid為空,即還沒啟動
sleep 0.1 # 等待0.1s
else
return # 啟動完成,退出方法
fi
elif [ ${action} = "STOP" ]; then # 指令為停止
if [ -z ${pid} ]; then # 如果pid為空,即服務停止了(未啟動)
return # 停止完成,退出方法
else
sleep 0.1 # 等待0.1s
fi
fi
done
}
# 啟動指定服務
start_service() {
i=$1 # 取傳入的第一個引數
service=${SERVICES_ARRAY[$i]} # 獲取服務名
extension=${SERVICES_EXTENSION[$i]} # 獲取字尾
# nohup 不結束通話地執行命令,使用nohup命令後,原程式的的標準輸出被自動改向到當前目錄下的nohup.out檔案
# > 表示重定向到哪裡
# /dev/null:表示Linux的空裝置檔案
# 2:表示標準錯誤輸出
# &1:&表示等同於的意思,2>&1,表示2的輸出重定向等於於1
# &:表示後臺執行,即這條指令執行在後臺執行
# " >/dev/null 2>&1 "常用來避免shell命令或者程式等執行中有內容輸出。
nohup java -jar ${service}.${extension} >/dev/null 2>&1 & # 執行java命令
if [ $? != 0 ]; then # 顯示最後命令的退出狀態。0表示沒有錯誤,其他任何值表明有錯誤。
echo "啟動 ${service} 服務失敗"
exit 1 # 退出 退出碼:非0表示失敗(Non-Zero - Failure)
fi
waiting_for_complete ${service}.${extension} START #等待啟動完成
}
# 停止指定服務
stop_service() {
i=$1 # 取傳入的第一個引數
service=${SERVICES_ARRAY[$i]} # 獲取服務名
extension=${SERVICES_EXTENSION[$i]} # 獲取字尾
pid=${PIDS_ARRAY[$i]} # 獲取pid
kill ${pid} # 通過pid停止服務(程式)
if [ $? != 0 ]; then # 顯示最後命令的退出狀態。0表示沒有錯誤,其他任何值表明有錯誤。
echo "停止 ${service} 服務失敗"
exit 1 # 退出 退出碼:非0表示失敗(Non-Zero - Failure)
fi
waiting_for_complete ${service}.${extension} STOP # 等待停止完成
}
# 啟動所有服務
start_all_service() {
# 遍歷陣列
for ((i=1; i<=$SERVICES_NUM; i++)); do
pid=${PIDS_ARRAY[$i]}
if [ -n "$pid" ]; then
stop_service ${i} # 先停止服務
fi
start_service ${i} # 再啟動服務
done
}
# 停止所有服務
stop_all_service() {
# 遍歷陣列
for ((i=1; i<=$SERVICES_NUM; i++)); do
pid=${PIDS_ARRAY[$i]}
if [ -n "$pid" ]; then
stop_service ${i} # 停止服務
fi
done
}
# 選擇服務及操作
choose_and_do_service() {
# 格式輸出
echo -e ${GREEN_BEGIN}" 選擇 [1-$SERVICES_NUM(啟動指定服務); s(啟動所有); p(停止所有)]: "${COLOR_END}"c"
read i # 讀取鍵盤輸入
# 特殊指令
if [ "$i" = "q" ]; then
exit 0 # 退出 退出碼:0表示成功
elif [ "$i" = "s" ]; then
start_all_service # 啟動全部服務
return
elif [ "$i" = "p" ]; then
stop_all_service # 停止所有服務
return
fi
# 選擇某個服務
# [0-9]{1,} 就是必須是數字,最少1位,最多不限制長度
echo "$i" | egrep "^[0-9]{1,}$" >/dev/null
# if [ $? -ne 0 ] 如果上一條命令執行後的結束程式碼不是0則執行下面的命令
# 大於最大服務號或者小於1,則屬於錯誤輸入
if [ $? -ne 0 ] || [ ${i} -gt ${SERVICES_NUM} ] || [ ${i} -lt 1 ]; then
echo -e ${RED_BEGIN}" 選擇存在錯誤"${COLOR_END} # 給出錯誤提示
return # 退出該方法
fi
pid=${PIDS_ARRAY[$i]}
# pid為空時表示服務未啟動
if [ -z "$pid" ]; then # -z 檢測字串長度是否為0,為0返回 true。
printf " 該服務處於未啟動狀態, 確定要啟動嗎? (Y/n) " # 提示是否啟動
read c # 讀取鍵盤輸入
# 大寫替換成小寫
c=$(echo ${c} | tr [A-Z] [a-z]) # tr的命令格式是tr SET1 SET2,凡是在SET1中的字元,都會被替換為SET2中相應位置上的字元
if [ "$c" = "y" -o "$c" = "" ]; then # -o 或運算,有一個表示式為 true 則返回 true。
start_service ${i} # 啟動指定服務
elif [ "$c" != "n" ]; then
echo -e ${RED_BEGIN}" 輸入存在錯誤"${COLOR_END}
fi
# 服務已經啟動
else
printf " 該服務處於啟動狀態,確定要停止嗎? (Y/n) " # 提示是否停止
read c # 讀取鍵盤輸入
# 大寫替換成小寫
c=$(echo ${c} | tr [A-Z] [a-z])
if [ "$c" = "y" -o "$c" = "" ]; then
stop_service ${i} # 停止指定服務
elif [ "$c" != "n" ]; then
echo -e ${RED_BEGIN}" 輸入存在錯誤"${COLOR_END}
fi
fi
}
while true; do
list_services # 呼叫列表展示方法
choose_and_do_service # 呼叫選擇操作方法
done
6、執行命令使start.sh檔案變為可執行檔案,命令如下:
chmod +x start.sh
7、執行start.sh檔案,命令如下:
./start.sh