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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。