shell_test專案介紹

pysasuke發表於2017-10-20

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

相關文章