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="\033[32m"    # 绿色
RED_BEGIN="\033[31m"    # 红色(用于错误提示)
COLOR_END="\033[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 "\033[字背景颜色;字体颜色m字符串\033[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\n" "$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

pysasuke
199 声望4 粉丝

青铜分段掌控雷电