shell之循环嵌套与扩展(函数)

目录:

  • 一、随机数
    • 1.实战案例:
    • 2.实战案例:
      • ①.优化:
  • 二、嵌套循环
    • 1.案例一:
    • 2.案例二:
    • 3.案例三(打印99乘法表):
  • 三、扩展shift
  • 四、expect程序交互
    • 1.变量定义:
    • 2.使用位置参数:
  • 五、expect和shell脚本结合使用
  • 六、综合案例
    • 1.实现:
  • 七、案例
  • 八、case语句
    • 1.案例一:
    • 2.案例二:
    • 3.应用案例:
      • ①.优化:
  • 九、函数
    • 1.函数的定义:
    • 2.函数的调用:
  • 十、函数中return说明
    • 1.应用案例:
    • 2.综合案例:

一、随机数

shell之循环嵌套与扩展(函数)_第1张图片
shell之循环嵌套与扩展(函数)_第2张图片

1.实战案例:

写一个脚本,产生一个phonenum.txt文件,随机产生以139开头的手机号100个,每个一行

分析

  • 产生100个电话号码,脚本需要循环100次
  • 139+8位,后8位随机产生,可以让每一位数字都随机产生,$[RANDOM%10]
  • 将随机产生的数字分别保存到变量里,然后加上139保存到文档里
    shell之循环嵌套与扩展(函数)_第3张图片

2.实战案例:

在上面的100个手机号码里抽奖5个幸运观众,显示出这5位幸运观众。但只显示头3个数和尾号的4个数,中间的都用*代替

思路:

  • 确定幸运观众所在的行 随机生成RANDOM
  • 将电话号码提取出来 head和tail
  • 显示前三位和后四位到屏幕中,最后将电话号码输出到屏幕
    shell之循环嵌套与扩展(函数)_第4张图片
    shell之循环嵌套与扩展(函数)_第5张图片
    shell之循环嵌套与扩展(函数)_第6张图片

①.优化:

当用户被抽到后,就从抽奖名单里删除,保证不被抽到两次

shell之循环嵌套与扩展(函数)_第7张图片
在这里插入图片描述

二、嵌套循环

一个循环体内又包含另一个完整的循环结构,称为循环的嵌套。在外部循环的每次执行过程中都会触发内部循环,直至内部完成一次循环,才接着执行下一次的外部循环。for循环,while循环和until循环可以相互嵌套

1.案例一:

shell之循环嵌套与扩展(函数)_第8张图片
shell之循环嵌套与扩展(函数)_第9张图片

2.案例二:

shell之循环嵌套与扩展(函数)_第10张图片
shell之循环嵌套与扩展(函数)_第11张图片

3.案例三(打印99乘法表):

shell之循环嵌套与扩展(函数)_第12张图片
shell之循环嵌套与扩展(函数)_第13张图片

三、扩展shift

使位置参数向左移动,默认移动 1 位,可以使用shift 2

shell之循环嵌套与扩展(函数)_第14张图片
在这里插入图片描述

四、expect程序交互

expect自动应答 tcl语言

远程登入到另一台主机上,啥也不做
shell之循环嵌套与扩展(函数)_第15张图片
两种执行方式(它不是shell脚本)shell之循环嵌套与扩展(函数)_第16张图片

登入到另一台主机上,创建文件
shell之循环嵌套与扩展(函数)_第17张图片
shell之循环嵌套与扩展(函数)_第18张图片
shell之循环嵌套与扩展(函数)_第19张图片

1.变量定义:

shell之循环嵌套与扩展(函数)_第20张图片

2.使用位置参数:

shell之循环嵌套与扩展(函数)_第21张图片

五、expect和shell脚本结合使用

shell脚本和expect结合使用,在多台服务器上创建1个用户

在这里插入图片描述
思路:

  • 循环
  • 登录远程主机–>ssh–>从ip.txt文件里获取ip和密码分别赋值给两个变量
  • 使用expect程序解决交互问题
    shell之循环嵌套与扩展(函数)_第22张图片

六、综合案例

写一个脚本,将跳板机上yunwei用户的公钥推送到局域网内可以ping通的所有主机上

案例分析:

  • 关闭防火墙和selinux
  • 循环判断局域网内哪些ip可以ping通
  • 密码文件里获取主机的ip和密码保存变量 ip pass
  • 判断公钥是否存在
  • ssh-copy-id将跳板机上的yunwei用户的公钥推送到远程主机上–>expect解决交互问题
  • 将ping通的主机的ip单独保存到文件中

代码拆分:

  • 获取ip并且判断是否可以ping通
  • 主机密码文件ip.txt
  • 循环判断主机是否能ping通
    • cat ip.txt|while read ip pass
      • do
        • ping -c1 $ip &>/dev/null
        • if [ $? -eq 0 ];then
        • 判断公钥是否存在
        • 推送公钥
        • fi
      • done
        • 判断yunwei用户的公钥是否存在
        • [ ! -f /home/yunwei/.ssh/id_rsa ] && ssh -P " " -f ./id_rsa
  • 非交互式推送公钥
    • /usr/bin/expect <<-END &>/dev/null
    • spawn ssh-copy-id root@$ip
    • expect {
      • “yes/no” { send “yes\r”;exp_continue }
      • “password” { send “$pass\r” }
    • }
    • expect eof
    • END

1.实现:

shell之循环嵌套与扩展(函数)_第23张图片
shell之循环嵌套与扩展(函数)_第24张图片
shell之循环嵌套与扩展(函数)_第25张图片

七、案例

写一个脚本,统计web服务器的不同连接状态个数
shell之循环嵌套与扩展(函数)_第26张图片

八、case语句

case语句为多选择语句。可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令
shell之循环嵌套与扩展(函数)_第27张图片

1.案例一:

当给程序传入start,stop,reload三个不同的参数时分别执行相应命令
shell之循环嵌套与扩展(函数)_第28张图片shell之循环嵌套与扩展(函数)_第29张图片

2.案例二:

脚本提示让用户输入需要管理的服务名,然后提示用户需要对服务做什么操作,如启动,关闭,重启等等
shell之循环嵌套与扩展(函数)_第30张图片

3.应用案例:

#!/bin/bash
#echo -e "h	显示命令帮助\nf	显示磁盘分区\nd	显示磁盘挂载\nm	查看内存使用\nu	查看系统负载\nq	退出程序"
cat <<-END
	h	显示命令帮助
	f	显示磁盘分区
	d	显示磁盘挂载
	m	查看内存使用
	u	查看系统负载
	q	退出程序
	END
read -p "请选择操作编号:" num
case $num in
     h)
     cat <<-END
        h       显示命令帮助
        f       显示磁盘分区
        d       显示磁盘挂载
        m       查看内存使用
        u       查看系统负载
        q       退出程序
	END
     ;;
     f)
     df -h
     ;;
     d)
     lsblk
     ;;
     m)
     free -h
     ;;
     u)
     uptime
     ;;
     q)
     exit
     ;;
esac

但是这样执行一次就结束了shell之循环嵌套与扩展(函数)_第31张图片

①.优化:

1.利用函数,减少代码量

#!/bin/bash
#echo -e "h	显示命令帮助\nf	显示磁盘分区\nd	显示磁盘挂载\nm	查看内存使用\nu	查看系统负载\nq	退出程序"
menu(){
         #这个是定义函数
cat <<-END
	h	显示命令帮助
	f	显示磁盘分区
	d	显示磁盘挂载
	m	查看内存使用
	u	查看系统负载
	q	退出程序
	END
}
menu  #调用函数
read -p "请选择操作编号:" num
case $num in
     h)
     menu  #调用函数
     ;; 
     f)
     df -h
     ;;
     d)
     lsblk
     ;;
     m)
     free -h
     ;;
     u)
     uptime
     ;;
     q)
     exit
     ;;
esac

让程序循环,直到自己按q退出才退出

#!/bin/bash
#echo -e "h	显示命令帮助\nf	显示磁盘分区\nd	显示磁盘挂载\nm	查看内存使用\nu	查看系统负载\nq	退出程序"
menu(){
     
cat <<-END
	h	显示命令帮助
	f	显示磁盘分区
	d	显示磁盘挂载
	m	查看内存使用
	u	查看系统负载
	q	退出程序
	END
}
menu
while true  #设置一个死循环,直至自己退出才退出
do
read -p "请选择操作编号:" num
case $num in
     h)
     menu
     ;;
     f)
     df -h
     ;;
     d)
     lsblk
     ;;
     m)
     free -h
     ;;
     u)
     uptime
     ;;
     q)
     exit
     ;;
esac
done

九、函数

shell中允许将一组命令集合或语句形成一段可用代码,这些代码称为shell函数。给这段代码起个名字为函数名,后续可以直接调用该段代码的功能

1.函数的定义:

shell之循环嵌套与扩展(函数)_第32张图片

2.函数的调用:

  • 如果是另外单独写的函数,保存后需要source这个文件,然后直接执行函数名即可
  • 另外写的函数文件,需要在脚本中用的话,在脚本中source一下,然后直接写函数名调用即可
  • 想要其他用户也可以使用的话,需要把函数的全部写进/etc/bashrc文件中

十、函数中return说明

  • return可以结束一个函数,类似于循环控制语句break(结束当前循环,执行循环体后面的代码)
  • return默认返回函数中最后一个命令的退出状态,也可以给定参数值,该参数值的范围是0-256之间
  • 如果没有return命令,函数将返回最后一个shell的退出值

1.应用案例:

需求:写一个脚本让用户输入基本信息(姓名,性别,年龄),如不输入一直提示输入,最后根据用户的信息输出相应的内容

思路:

  • 循环直到输入字符串不为空(该功能可以定义为一个函数,方便调用)
  • 根据用户输入信息做出匹配判断 case语句
#!/bin/bash
input_fun(){
     
   input_var=""
   output_var=$1
   while [ -z $input_var ]
     do
       read -p "$output_var" input_var
     done
     echo $input_var
}
name=$(input_fun 请输入您的姓名:)
sex=$(input_fun 请输入您的性别:)
age=$(input_fun 请输入您的年龄:)
echo $name
echo $sex
echo $age
case $sex in)
  if [ $age -gt 18 -a $age -le 35 ];then
      echo "中年叔叔您油腻了吗?快快加油哦!"
  elif [ $age -gt 35 ];then
    echo "保温杯里泡枸杞!"
  else
    echo "年轻有为!"
  fi
  ;;)
  if [ $age -gt 18 -a -le 35 ];then
    echo "女人到一定年纪得注意保养!"
  elif [ $age -gt 35 ];then
    echo "人到中年,注意控制脾气!"
  else 
    echo "青春活力美少女!"
  fi
  ;;
esac

2.综合案例:

任务背景:
现有的跳板机虽然实现了统一入口来访问生产服务器,yunwei用户权限太大可以操作跳板机上的所有目录文件,存在数据被误删的隐患,所以希望做一些安全策略保证跳板机正常使用

具体要求:

  • 只允yunwei用户通过跳板机远程连接后台的应用服务器做一些维护操作
  • 公司运维人员远程通过yunwei用户连接跳板机时,跳出以下菜单供选择
  • 当用户选择相应的主机后,直接免密成功登入
  • 如果用户不输入一直提示用户输入,知道用户选择退出

分析:

  • 打印菜单–>定义函数 echo cat
  • 让用户选择需要操作的机器 ---->case…esac
  • 配置免密登入
  • 每个菜单提供选择功能—>case…esac用户选择做的事情
  • 循环让用户输入选择
  • 每个功能写成函数—>非必须
  • 脚本放的位置------>yunwei用户家目录
    为了让它一直停留在跳板机界面,在家目录下的bashrc下写bash 脚本名字和exit

shell之循环嵌套与扩展(函数)_第33张图片

#!/bin/bash
#jump-server
#定义函数
#定义菜单打印的功能
trap '' 1 2 3 19
menu(){
     
  cat<<-EOF
  欢迎使用jump-server,请选择您要操作的主机:
  1.DB-Master
  2.DB-Slave
  3.web1
  4.web2
  h.help
  q.exit
	EOF
}
menu1(){
     
  cat<<-EOF
  欢迎进入web-server,请选择你要操作的内容:
  1.清理日志
  2.启动Apache
  3.重启Apache
  h.help 
	EOF
}
menu
while true
do
#用户选择相应的主机操作
read -p "请选择您要操作的主机:" host
case $host in
       1)
       ssh [email protected]
       ;;
       2)
       ;;
       3)
       menu1
       read -p "请输入你要操作的内容:" actions
       case $actions in
                 1)
                 ssh [email protected]
                 echo "日志正在清理中!"
                 ;;
                 2)
                 ssh [email protected]
                 systemctl start httpd
                 ;;
                 3)
                 ssh [email protected]
                 systemctl restart httpd
                 ;;
                 h)
                 menu1
                 ;;
                 *)
                     echo "请选择您要操作的主机:"
                 ;;
       esac
       menu
       ;;
       4)
       ;;
       h)
       menu
       ;;
       q)
       exit
       ;;
esac
done

你可能感兴趣的:(shell)