case控制语句
1.什么是case
case条件语句相当于多分支的if/elif/else条件语句,主要还是用来做条件判断的,常被应用于实现系统服务启动脚本。
case语句中,会将case获取的变量值与表达式部分的值1、值2、值3等逐个进行比较,如果变量值和某个表达式的值(例如值1)相匹配,就会执行值(例如值1)后面对应的指令(例如指令1,其可能是一组指令),直到执行到双分号(;;)才停止,然后再跳出case语句主体,执行case语句(即esac字符)后面的其他命令。
如果没有找到匹配变量的任何值,则执行“*)”后面的指令(通常是给使用者的使用提示),直到遇到双分号(;;)此处的双分号可以省略或esac结束,这部分相当于if多分支语句中最后的else语句部分。
2.case的使用场景
- 1.服务启停脚本 start、stop、restart、
- 2.监控本地nginx状态,php状态这类脚本
- 3.条件匹配,菜单选择时,必用case
3.case基础语法示例
-
case 变量 in start) 执行的代码 ;; stop) 执行的代码 ;; restart) 执行的代码 ;; *) echo "Usage: $0 [ start | stop | restart ]" esac
案例1:
根据输入的编号,输出对应的字符串
#!/bin/bash
cat <<eof
****************
** 1. backup **
** 2. copy **
** 3. quit **
****************
eof
read -p "输入你选择的编号:" action
case $action in
1|backup) #使用竖线|可以匹配1或者backup,也就是可以用竖线来匹配多个值。
echo "backup..."
;; #双封号记得要加
2|copy)
echo "copy..."
;;
3)
exit
;;
*) #没有匹配到任何值,则执行“*)”后面的指令
echo "Usage: $0 [ 1 | 2 | 3 ]"
exit
esac
案例2:
使用case来完成nginx服务的启动与停止,重启。
#!/bin/bash
source /etc/init.d/functions
case $1 in
start)
ngx_status=$(pidof nginx |wc -l)
if [ $ngx_status -eq 1 ];then #如果返回1,说明有nginx进程,就无需再次启动
action "nginx is starting" /bin/false
else
systemctl start nginx
action "nginx is starting" /bin/true
fi
;;
stop)
pkill nginx
if [ $? -eq 0 ];then
action "nginx is stoped" /bin/true
else
action "nginx is stoped" /bin/false
fi
;;
restart)
pkill nginx && systemctl start nginx
if [ $? -eq 0 ];then
action "nginx is restart" /bin/true
else
action "nginx is restart" /bin/false
fi
;;
status)
systemctl status nginx
;;
*)
echo "usage :$0 [ start | stop | restart | status ]"
exit
esac
执行效果:
案例3:
使用case编写监控nginx状态脚本
思路梳理:
获取nginx的状态 7种状态,将每种提取出来,然后执行脚本,根据用户输入的状态名称,输出状态值即可
如何获取nginx的七种状态指标?
vim /etc/nginx/conf.d/test.conf
server{
listen 88; #网站监听的端口
server_name www.test.com; #定义网站访问的域名
location / { #(location是用于控制用户请求的URI的路径的)
root /test; #定义站点代码存放的路径(根路径)
index index.html; #定义站点默认返回的页面
}
location /ngx_status {
stub_status; #展示nginx种状态指标
}
}
语法检测,重载nginx
nginx -t
systemctl reload nginx
查看状态指标结果
Active connections 当前的活跃连接数 ( 包含 waiting )
accepts 已接收的TCP连接数。
handled 已处理的TCP连接数。
requests 总的HTTP请求数。 (请求数大于连接数是正常的,因为一个连接可以创建多个请求)
Reading: nginx 读取到客户端的Header信息数
Writing: nginx 返回给客户端的Header信息数
Waiting: Nginx已经处理完,正在等候下一次请求指令的驻留链接
脚本:
#!/bin/bash
read -p "输入要查看的状态指标: [ active_conn | accepts | handled | requests | reading | writing | waiting ]" action
case $action in
active_conn)
curl -s 127.0.0.1:88/ngx_status|awk -F ':' '/Active connections/{print $2}'
;;
accepts)
curl -s 127.0.0.1:88/ngx_status|awk 'NR==3{print $1}'
;;
handled)
curl -s 127.0.0.1:88/ngx_status|awk 'NR==3{print $2}'
;;
requests)
curl -s 127.0.0.1:88/ngx_status|awk 'NR==3{print $3}'
;;
reading)
curl -s 127.0.0.1:88/ngx_status|awk -F '[: ]+' 'NR==4{print $2}'
;;
writing)
curl -s 127.0.0.1:88/ngx_status|awk -F '[: ]+' 'NR==4{print $4}'
;;
waiting)
curl -s 127.0.0.1:88/ngx_status|awk -F '[: ]+' 'NR==4{print $6}'
;;
*)
echo "usage 输入下列指标: [ active_conn | accepts | handled | requests | reading | writing | waiting ]"
;;
esac
执行效果:
案例4:
使用case编写监控php-fpm状态脚本
如何开启php-fpm的状态?
开启php-fpm的状态
vim /etc/php-fpm.d/www.conf
找到该行并去掉前面的注释
pm.status_path = /fpm_status
systemctl restart php-fpm
配置nginx,让其通过http协议能获取php的状态信息
server{
listen 89;
server_name www.test.com;
root /test;
location / {
index index.php index.html;
}
#将php结尾的请求文件都传递给本地php服务端处理
location ~ \.php$ { #通过location进行匹配,访问的URI为.php结尾的都走这个location
fastcgi_pass 127.0.0.1:9000; #将php结尾的请求文件都传递给本地php服务端处理
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; #为SCRIPT_FILENAME变量设定值(具体要解析的文件路径)
include fastcgi_params;
}
#如果有请求fpm_status则交给php处理
location /fpm_status {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
初始化本地目录文件
cat /test/index.php
<?php phpinfo(); ?>
语法检测,重载nginx
nginx -t
systemctl reload nginx
查看效果
curl一下查看php-fpm状态
#!/bin/bash
read -p "输入要查看的指标: [ pool | process manager | start time | start since | accepted conn | listen queue | max listen queue |listen queue len | idle processes |active processes |total processes |max active processes |max children reached |slow requests ]:" action
case $action in
"pool")
curl -s 127.0.0.1:89/fpm_status | awk '/pool/{print $2}'
;;
"process manager") #带空格的表达式,用双引号括起来,不然无法匹配
curl -s 127.0.0.1:89/fpm_status | awk -F ': +' '/process manager/{print $2}'
;;
"start time")
curl -s 127.0.0.1:89/fpm_status | awk -F ': +' '/start time/{print $2}'
;;
"start since")
curl -s 127.0.0.1:89/fpm_status | awk -F ': +' '/start since/{print $2}'
;;
"accepted conn")
curl -s 127.0.0.1:89/fpm_status | awk -F ': +' '/accepted conn/{print $2}'
;;
"listen queue")
curl -s 127.0.0.1:89/fpm_status | awk -F ': +' '/^listen queue:/{print $2}'
;;
"max listen queue")
curl -s 127.0.0.1:89/fpm_status | awk -F ': +' '/max listen queue/{print $2}'
;;
"listen queue len")
curl -s 127.0.0.1:89/fpm_status | awk -F ': +' '/listen queue len/{print $2}'
;;
"idle processes")
curl -s 127.0.0.1:89/fpm_status | awk -F ': +' '/idle processes/{print $2}'
;;
"active processes")
curl -s 127.0.0.1:89/fpm_status | awk -F ': +' '/^active processes/{print $2}'
;;
"total processes")
curl -s 127.0.0.1:89/fpm_status | awk -F ': +' '/total processes/{print $2}'
;;
"max active processes")
curl -s 127.0.0.1:89/fpm_status | awk -F ': +' '/max active processes/{print $2}'
;;
"max children reached")
curl -s 127.0.0.1:89/fpm_status | awk -F ': +' '/max children reached/{print $2}'
;;
"slow requests")
curl -s 127.0.0.1:89/fpm_status | awk -F ': +' '/slow requests/{print $2}'
;;
*)
echo "usage 输入下列指标: [ pool | process manager | start time | start since | accepted conn | listen queue | max listen queue |listen queue len | idle processes |active processes |total processes |max active processes |max children reached |slow requests ]"
;;
esac
脚本执行效果
案例5:
编写脚本,根据用户输入的服务名称查询该服务的状态,如果服务不存在则直接报错。
如果服务启动则提示 [重启和停止操作],如果服务没有启动则提示 [启动和取消操作]
思路分析:
1.判断服务是否存在,不存在则直接报错
2.检查服务是否启动,
如果启动,则提示重启或停止
如果停止,则提示启动或取消操作
可以加入限定脚本的执行权限,只有root才能执行该脚本
先执行systemctl status 服务名
,再执行echo $?
来返回上一条命令执行返回的结果
得出
0: 启动
3: 停止
4: 不存在
#!/bin/bash
#1.确保该脚本是root用户执行
if [ $USER != "root" ];then
echo "$USER 对脚本 $0 没有执行权限!"
exit
fi
#2.确保用户只能传递一个参数
if [ $# -ne 1 ];then
echo "使用脚本 $0 时只能传递一个参数"
exit
fi
#3.判断用户传递的服务名称情况
systemctl status $1 &>/dev/null
rc=$?
#4.如果服务不存在则报错
if [ $rc -eq 4 ];then
echo "服务 $1 不存在"
exit
#5.检查服务是否启动或者是停止
elif [ $rc -eq 0 ];then
read -p "当前 $1 处于启动状态是否需要[ stop | restart ]" action
case $action in
stop)
systemctl stop $1
;;
restart)
systemctl restart $1
;;
*)
echo "请输入[ stop | restart]"
exit
;;
esac
#6.检查服务是否停止,停止则提示启动或取消操作
elif [ $rc -eq 3 ];then
read -p "当前 $1 处于停止状态是否需要[ start |quit ]" action1
case $action1 in
start)
systemctl start $1
;;
quit)
exit
;;
*)
echo "请输入[ start | quit]"
exit
;;
esac
fi
脚本执行效果:
案例6:
以nginx为例,升级一下nginx的错误定向,当服务启动失败时候,可以选择修复,选择修复,就直接定位到报错的文件的具体行进行修复。
思路梳理:
根据nginx -t的输出,就可以定位到有问题的文件和有问题的行
将有问题的文件和有问题的行取出来
当选择修复时,直接编辑该文件的问题行即可
vim 问题文件 +问题行
#!/bin/bash
if [ $USER != "root" ];then
echo "$USER 对脚本 $0 没有执行权限!"
exit
fi
if [ $# -ne 1 ];then
echo "使用脚本 $0 时只能传递一个参数"
exit
fi
systemctl status $1 &>/dev/null
rc=$?
if [ $rc -eq 4 ];then
echo "服务 $1 不存在"
exit
elif [ $rc -eq 0 ];then
read -p "当前 $1 处于启动状态是否需要[ stop | restart ]" action
case $action in
stop)
systemctl stop $1
;;
restart)
systemctl restart $1
;;
*)
echo "请输入[ stop | restart]"
exit
;;
esac
elif [ $rc -eq 3 ];then
read -p "当前 $1 处于停止状态是否需要[ start |quit ]" action1
case $action1 in
start)
systemctl start $1 &>/dev/null
if [ $? -eq 0 ];then
echo "启动成功!"
else
read -p "服务 $1 启动失败,是否尝试修复[ repair|quit ]" action2
case $action2 in
repair)
nginx -t &> ngx.tmp
ngx_conf=$(awk -F '[: ]' 'NR==1 {print $8}' ngx.tmp) #哪个文件有问题
ngx_line=$(awk -F '[: ]' 'NR==1 {print $9}' ngx.tmp)#哪行有问题
vim ${ngx_conf} +${ngx_line} #直接定位到有问题的文件的有问题的那一行进行更改
;;
quit)
exit
;;
*)
echo "输入有误!再见"
;;
esac
fi
;;
quit)
exit
;;
*)
echo "请输入[ start | quit]"
exit
;;
esac
fi
脚本执行效果:
输入修复选项,就直接打开了有问题的那个文件,并定位到了有问题的那行
修复完后,就可以成功启动了