Day03-SHELL自动化编程-case与函数
9.3 case语句
9.3.1 概述
-
条件分支语句,一般用于实现有多种选择的脚本。
-
这个功能:if或多分支if实现,如果使用case语句会更加清晰直观.
-
菜单。
-
start|stop|restart|status
# case语句格式
case "变量" in
start)
命令1
;;
stop)
命令2
;;
restart)
命令3
;;
*)
错误提示
esac
#if格式
if [ "$cmd" = "start" ]
then
echo "start"
elif [ "$cmd" = "stop" ]
then
echo "stop"
elif [ "$cmd" = "restart" ]
then
echo "restart"
else
echo "错误"
fi
case语句 vs if多分支
case 一般用于固定的菜单选择情况,运行脚本用户输入1,2,3,4,start|stop|restart…
if 可以用于一些范围的比较。
eg9.3-运行脚本用户输入自己的选择,可以输入linux,dba,k8s,monitor,sre,devops,选择后输出你选择了xxx.方向
9.3.2 格式与实践
case格式
case "变量" in
选择1)
命令
;;
选择2)
命令
,,
*)
命令(保底的默认输出)
esac
- 使用case进行修改后的脚本
案例18-某会所菜单展示程序
- oldwang会所的菜单功能(套餐)
- 输出可选的套餐
- 138套餐) 吃饱套餐
- 443套餐) 吃饱喝足套餐
- 888套餐) 吃喝拉撒套餐
- 1688套餐) 你想干啥就干啥套餐
- 8080套餐) 隐藏不便显示
- 8443套餐) 隐藏老板娘套餐
- 其他) 劝退套餐
[root@m01 devops-shell]# cat 18-case_menu.sh
#!/bin/bash
##############################################################
# File Name:18-case_menu.sh
# Version:V1.0
# Author:oldboy lidao996
# Organization:www.oldboyedu.com
# Desc:
##############################################################
#1.输出
cat <<EOF
- oldwang会所的菜单功能(套餐)
- 输出可选的套餐
输入1选择 138套餐) 吃饱套餐
输入2选择 443套餐) 吃饱喝足套餐
输入3选择 888套餐) 吃喝拉撒套餐
输入4选择 1688套餐) 你想干啥就干啥套餐
- 其他) 劝退套餐
EOF
#2.获取用户的输入
read -p "尊敬的VIP用户,请输入您的选择:" num
#3.根据用户的输入,输出对应的信息
case "$num" in
1)
echo "138套餐"
;;
2)
echo "443套餐"
;;
3)
echo "888套餐"
;;
4)
echo "1688套餐"
;;
5)
echo "尊敬的SSSSSVIP用户,恭喜激活8080不便显示套餐"
;;
6)
echo "尊敬的SSSSSVIP用户,恭喜激活8443老板娘套餐"
;;
*)
echo "选择错误,请充值"
esac
[root@m01 devops-shell]# sh 18-case_menu.sh
- oldwang会所的菜单功能(套餐)
- 输出可选的套餐
输入1选择 138套餐) 吃饱套餐
输入2选择 443套餐) 吃饱喝足套餐
输入3选择 888套餐) 吃喝拉撒套餐
输入4选择 1688套餐) 你想干啥就干啥套餐
- 其他) 劝退套餐
尊敬的VIP用户,请输入您的选择:4
1688套餐
[root@m01 devops-shell]# sh 18-case_menu.sh
- oldwang会所的菜单功能(套餐)
- 输出可选的套餐
输入1选择 138套餐) 吃饱套餐
输入2选择 443套餐) 吃饱喝足套餐
输入3选择 888套餐) 吃喝拉撒套餐
输入4选择 1688套餐) 你想干啥就干啥套餐
- 其他) 劝退套餐
尊敬的VIP用户,请输入您的选择:6
尊敬的SSSSSVIP用户,恭喜激活8443老板娘套餐
9.3.3 小结
-
case语句功能,可以通过if+elif+else形式进行替换。
-
应用场景:同一个变量有多个结果的时候(多种选择的时候),选用case语句,较为清晰。
-
case清晰,适用于菜单输入与选择,服务启动,关闭,重启脚本。
-
进阶格式:
- 分支中可以使用|表示或者
- *号表示所有
案例19-判断用户输入的是yes还是no
用户输入yes,y,Y,Yes 都表示yes
用户输入no,n,N,No 都表示no
[root@m01 devops-shell]# cat 19-case_yesno.sh
#!/bin/bash
##############################################################
# File Name:19-case_yesno.sh
# Version:V1.0
# Author:oldboy lidao996
# Organization:www.oldboyedu.com
# Desc:
##############################################################
read -p "input yes or no:" xuan
#choice
case "$xuan" in
yes|y|Y|Yes) echo "您输入的是yes" ;;
no|n|N|No) echo "您输入的是yno" ;;
esac
[root@m01 devops-shell]# sh 19-case_yesno.sh
input yes or no:y
您输入的是yes
9.5 判断小结
-
条件表达式格式: [] [[]] test , (())
-
判断文件,字符串,大小,逻辑,正则
-
if判断:
- 单分支。
- 双分支。
- 多分支。
-
case语句: 用户输入与不同的选择,相对固定的选择.
-
完成案例:比大小,输出指定用户信息,服务管理脚本(优化)。
10. SHELL编程-函数
- 从入门到大神必会技术点
10.1 概述
-
把一堆代码,起个名字。
-
对脚本中重复使用到的代码,设置函数,精简脚本的内容。
-
让脚本更加的规范。
-
应用场景:
- 在书写脚本的时候,尽量使用函数,规范脚本。
- 让脚本的开发,更加模块化。
- 方便后期调试,调试的时候只需要注释函数即可。
echo "welcome to oldboy linux lidao996 class"
echo "你的目标:拿下15k offer"
echo "你的目标:拿下100+ shell脚本"
echo "你的目标:书写总共超过5000行脚本"
10.2 格式及实战应用
- 函数格式:
#定义方式01 最完整
function lidao_show() {
命令
命令
内容
return n #函数的返回值
}
#定义方式02 精简写法 一般使用这一种.
lidao_show() {
命令
命令
内容
return n #函数的返回值
}
#定义方式03
function lidao_show {
命令
命令
内容
return n #函数的返回值
}
案例20-函数基本格式与使用
[root@m01 devops-shell]# cat 20-test_func.sh
#!/bin/bash
##############################################################
# File Name:20-test_func.sh
# Version:V1.0
# Author:oldboy lidao996
# Organization:www.oldboyedu.com
# Desc:
##############################################################
show() {
echo "welcome to oldboy linux lidao996 class"
echo "你的目标:拿下15k offer"
echo "你的目标:拿下100+ shell脚本"
echo "你的目标:书写总共超过5000行脚本"
}
show
[root@m01 devops-shell]# sh -x 20-test_func.sh
+ show
+ echo 'welcome to oldboy linux lidao996 class'
welcome to oldboy linux lidao996 class
+ echo '你的目标:拿下15k offer'
你的目标:拿下15k offer
+ echo '你的目标:拿下100+ shell脚本'
你的目标:拿下100+ shell脚本
+ echo 你的目标:书写总共超过5000行脚本
你的目标:书写总共超过5000行脚本
10.3 函数传参
- 函数传参与脚本传参类似。使用$xxxxx形式进行
位置参数 | shell脚本中 | 函数中 |
---|---|---|
$n | 脚本的第n个参数 | 函数的第n个参数 |
$0 | 脚本的名字 | 脚本的名字 |
$# | 脚本的参数的格式 | 函数参数个数 |
@ / @/ @/* | 脚本所有的参数 | 函数所有的参数 |
案例21-函数传参案例
sh 21.show_func.sh lidao996
把脚本的$1参数传递到show函数中.
show函数的参数个数:1
show函数的所有参数:lidao996
lidao996.com
lidao996.cn
lidao996.org
lidao996.企业
lidao996.icu
lidao996.我爱你
[root@m01 devops-shell]# cat 21-func_params.sh
#!/bin/bash
##############################################################
# File Name:21-func_params.sh
# Version:V1.0
# Author:oldboy lidao996
# Organization:www.oldboyedu.com
# Desc:
##############################################################
show() {
cat <<EOF
show函数的参数个数:$#
show函数的所有参数:$*
$1.com
$1.cn
$1.org
$1.企业
$1.icu
$1.我爱你
EOF
}
show lidao996 lidao--7
#show $1 #这是脚本的第1个参数
[root@m01 devops-shell]# sh 21-func_params.sh
show函数的参数个数:2
show函数的所有参数:lidao996 lidao--7
lidao996.com
lidao996.cn
lidao996.org
lidao996.企业
lidao996.icu
lidao996.我爱你
[root@m01 devops-shell]# cat 21-func_params.sh
#!/bin/bash
##############################################################
# File Name:21-func_params.sh
# Version:V1.0
# Author:oldboy lidao996
# Organization:www.oldboyedu.com
# Desc:
##############################################################
show() {
cat <<EOF
show函数的参数个数:$#
show函数的所有参数:$*
$1.com
$1.cn
$1.org
$1.企业
$1.icu
$1.我爱你
EOF
}
#show lidao996 lidao--7
show $1 #这是脚本的第1个参数
[root@m01 devops-shell]# sh 21-func_params.sh lidao007
show函数的参数个数:1
show函数的所有参数:lidao007
lidao007.com
lidao007.cn
lidao007.org
lidao007.企业
lidao007.icu
lidao007.我爱你
10.4 案例22-sersync服务管理脚本
-
目标:书写服务管理脚本
- /server/scripts/xxxx {start|stop|restart|status}
-
服务是编译安装,二进制包。
-
流程:
- 找命令:
- 找出开启服务的命令.
- 找出关闭服务的命令.
- 找出重启服务的命令.
- 找出查看服务状态的命令.
- 找命令:
-
写脚本:case语句
-
调试
1)需求分析
-
sersync
-
书写data_sync.sh脚本,用于管理sersync服务.
-
sh data_sync.sh start|stop|restart|status
-
分析
- 如果用户输入的是start,则运行sersync启动的命令。
- 如果用户输入的是stop,则运行关闭sersync的命令。
- 如果用户输入的是status,则显示sersync是否运行中,pid。
- 如果用户输入的是restart,则运行stop的命令,然后运行start的命令。
- 如果用户输入的是其他的内容,则提示输入错误,提示格式。
先书写脚本骨架
[root@m01 devops-shell]# cat 22-sersync.sh
#!/bin/bash
##############################################################
# File Name:22-sersync.sh
# Version:V1.0
# Author:oldboy lidao996
# Organization:www.oldboyedu.com
# Desc:
##############################################################
#函数使用建议,根据步骤创建函数
#1.vars
choice=1
#2.定义函数
#2.0加入检查类函数
#命令是否存在
#配置文件是否存在
#2.1 启动服务的函数
sersync_start() {
sersync2 -rdo /app/tools/sersync/confxml.xml
}
#2.2 关闭服务的函数
sersync_stop() {
sersync_pid=`ps -ef |grep sersync2|grep -v grep |awk '{print $2}'`
kill $sersync_pid
}
#2.3 重启服务的函数
sersync_restart() {
sersync_pid=`ps -ef |grep sersync2|grep -v grep |awk '{print $2}'`
kill $sersync_pid
sersync2 -rdo /app/tools/sersync/confxml.xml
}
#2.4 服务状态的函数
sersync_status() {
#判断服务是否运行
##如果运行则显示 sersync is running(pid)
##如果没有运行显示 sersync is gualed
#检查服务的进程数量
sersync_count=`ps -ef |grep sersync2 |grep -v grep |wc -l`
if [ $sersync_count -eq 0 ]
then
echo "sersync is gualed"
else
sersync_pid=`ps -ef |grep sersync2|grep -v grep |awk '{print $2}'`
echo "sersync is running ${sersync_pid}"
fi
}
#2.5 用户输入异常提示
error_msg() {
echo "Usage: $0 {start|stop|restart|status}"
}
#3.case语句引用函数 脚本主要部分
case "$choice" in
start) sersync_start ;;
stop) sersync_stop ;;
restart) sersync_restart ;;
status) sersync_status ;;
*) error_msg ;;
esac
10.5 小结
- 应用:书写脚本尽量使用变量,函数规范脚本。
- 使用函数流程:分析问题,列出步骤,步骤 --> 命令 --> 函数。
- 函数传参:$* $@ $n $0
案例题一
脚本执行
sh /server/scripts/exam01-backup dir.sh /etc/
要求:(共计4项要求)
1.备份到/backup/_etc_2023-01-01.tar.gz #目录中所有的斜线替换为_
2.要检查用户指定的目录是否存在,不存在则提示目录不存在或者不是目录,然后退出脚本。
3.如果用户指定备份根目录,则提示开玩笑,你要备份根?然后退出脚本。
4.备份的目录就是固定为/backup/
脚本流程:
1.命令行传参dir=$1
2.检查目录是否存在?-d
3.检查目录是否是根目录?如果是提示…
4.进行处理与备份
[root@m01 devops-shell]# cat exam01.bakup_dir.sh
#!/bin/bash
##############################################################
# File Name:exam01.backup_dir.sh
# Version:V1.0
# Author:oldboy lidao996
# Organization:www.oldboyedu.com
# Desc:
##############################################################
#函数使用建议,根据步骤创建函数
#1.vars
dir=$1
#2.检查是否为目录
backup_dir_check() {
[ -d "$dir" ] || {
echo "请输入目录"
exit 1
}
}
#3.检查是否为根目录
backup_root_check() {
[ "$dir" = "/" ] && {
echo "开玩笑,你要备份根?"
exit 2
}
}
#4.进行备份处理
backup_dir() {
dir_new=`echo $dir /sed 's#/#_#g'`
[ ! -d /backup/ ] && mkdir -p /backup/
tar zcf /backup/${die_new}-`date +%F`.tar.gz $dir &>/dev/null
}
#5.调用函数
main() {
backup_dir_check
backup_root_check
backup_dir
}
main
案例题二
sh /sever/scripts/exam2_user_check.sh
要求:(共计:2+6+7=15项要求)
1.执行脚本后进行交互式提示。
2.输入1进行系统用户检查。输入2进行指定用户信息检查。
3.如果用户输入1则进行系统用户检查,要求输出如下内容。
1)系统一共有多少用户(所有用户,普通用户和虚拟用户都算)
2)可以登录用户有多少?
3)可以登录系统用户的用户名。
4)root用户最后一次登录时间和ip。
5)输出/home/目录占用磁盘空间。
6)输出/root/用户占用磁盘空空间。
4.如果用户输入2则检查指定用户信息。
1)检查用户是否存在,不存在则提示并退出脚本。
2)如果用户存在输出下面信息。
3)用户名
4)用户uid
5)用户gid
6)用户家目录
7)用户是否可以登录(如果是/bin/bash则可以登录)
步骤:
1.执行脚本,read提示用户进行输入num
2.如果用户输入1
1)系统一共有多少用户(所有用户,普通用户和虚拟用户都算)
2)可以登录用户有多少?
3)可以登录系统用户的用户名。
4)root用户最后一次登录时间和ip。
5)输出/home/目录占用磁盘空间。
6)输出/root/用户占用磁盘空空间。
3.如果用户输入2
1)检查用户是否存在,不存在则提示并退出脚本。
2)如果用户存在输出下面信息。
3)用户名
4)用户uid
5)用户gid
6)用户家目录
7)用户是否可以登录(如果是/bin/bash则可以登录)
[root@m01 devops-shell]# cat exam02.check_user.sh
#!/bin/bash
##############################################################
# File Name:exam02.check_user.sh
# Version:V1.0
# Author:oldboy lidao996
# Organization:www.oldboyedu.com
# Desc:
##############################################################
#1.vars
user_check_welcome() {
cat <<EOF
输入数字选择对应的功能:
1. 对系统所有用户进行巡检
2. 对某个用户进行巡检
EOF
read num
}
#2.如果选择1 系统用户巡检
user_all_check() {
#系统一共有多少用户
user_all_count=`wc -l /etc/passwd | awk '{print $1}'`
#可以登录用户有多少
user_all_login=`grep -c '/bin/bash' /etc/passwd`
#可以登录系统用户的用户名
user_all_login_username=`grep '/bin/bash' /etc/passwd | awk -F: '{print $1}' |xargs`
#root用户最后一次登录时间和ip
user_root_lastlog=`lastlog -u root|tail -1`
#输出/home/目录占用磁盘空间
home_dir_size=`du -sh /home/ |awk '{print $1}'`
#输出/root/用户占用磁盘空空间
root_dir_size=`du -sh /root/ |awk '{print $1}'`
cat<<EOF
系统一共有多少用户:$user_all_count
可以登录用户有多少:$user_all_login
可以登录系统用户的用户名:$user_all_login_username
root用户最后一次登录时间和ip:$user_root_lastlog
输出/home/目录占用磁盘空间:$home_dir_size
输出/root/用户占用磁盘空空间:$root_dir_size
EOF
}
#3.如果选择2 用户巡检
check_user_exist() {
read -p "请指定用户:" user
[ -z "$user" ] && user=root
id $user &>/dev/null || {
echo "$user 用户不存在"
exit 1
}
}
user_one_check() {
check_user_exist
user_shell=`grep "^${user}:" /etc/passwd | awk -F: '{print $NF}'`
if [ "$user_shell" = "/bin/bash" ];then
user_login="可以登录"
else
user_login="不可以登录"
fi
user_uid=`grep "^${user}:" /etc/passwd | awk -F: '{print $3}'`
user_gid=`grep "^${user}:" /etc/passwd | awk -F: '{print $4}'`
user_homedir=`grep "^${user}:" /etc/passwd | awk -F: '{print $(NF-1)}'`
user_lastlog=`lastlog | grep -w "${user}"`
echo "##############################################"
echo "####用户名:${user}"
echo "####用户uid:${user_uid}"
echo "####用户gid:${user_gid}"
echo "####用户是否可以登录:${user_login}"
echo "####用户家目录:${user_homedir}"
echo "####用户最后一次登录情况:${user_lastlog}"
echo "##############################################"
}
#4.all in one
all() {
user_check_welcome
case "$num" in
1) user_all_check ;;
2) user_one_check ;;
*) echo "请按照要求输入"
esac
}
all