shell之循环嵌套与扩展(函数)
Posted ღ᭄小艾ヅ࿐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shell之循环嵌套与扩展(函数)相关的知识,希望对你有一定的参考价值。
目录:
一、随机数
1.实战案例:
写一个脚本,产生一个phonenum.txt文件,随机产生以139开头的手机号100个,每个一行
分析
- 产生100个电话号码,脚本需要循环100次
- 139+8位,后8位随机产生,可以让每一位数字都随机产生,$[RANDOM%10]
- 将随机产生的数字分别保存到变量里,然后加上139保存到文档里
2.实战案例:
在上面的100个手机号码里抽奖5个幸运观众,显示出这5位幸运观众。但只显示头3个数和尾号的4个数,中间的都用*代替
思路:
- 确定幸运观众所在的行 随机生成RANDOM
- 将电话号码提取出来 head和tail
- 显示前三位和后四位到屏幕中,最后将电话号码输出到屏幕
①.优化:
当用户被抽到后,就从抽奖名单里删除,保证不被抽到两次
二、嵌套循环
一个循环体内又包含另一个完整的循环结构,称为循环的嵌套。在外部循环的每次执行过程中都会触发内部循环,直至内部完成一次循环,才接着执行下一次的外部循环。for循环,while循环和until循环可以相互嵌套
1.案例一:
2.案例二:
3.案例三(打印99乘法表):
三、扩展shift
使位置参数向左移动,默认移动 1 位,可以使用shift 2
四、expect程序交互
expect自动应答 tcl语言
远程登入到另一台主机上,啥也不做
两种执行方式(它不是shell脚本)
登入到另一台主机上,创建文件
1.变量定义:
2.使用位置参数:
五、expect和shell脚本结合使用
shell脚本和expect结合使用,在多台服务器上创建1个用户
思路:
- 循环
- 登录远程主机–>ssh–>从ip.txt文件里获取ip和密码分别赋值给两个变量
- 使用expect程序解决交互问题
六、综合案例
写一个脚本,将跳板机上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.实现:
七、案例
写一个脚本,统计web服务器的不同连接状态个数
八、case语句
case语句为多选择语句。可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令
1.案例一:
当给程序传入start,stop,reload三个不同的参数时分别执行相应命令
2.案例二:
脚本提示让用户输入需要管理的服务名,然后提示用户需要对服务做什么操作,如启动,关闭,重启等等
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
但是这样执行一次就结束了
①.优化:
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.函数的定义:
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
#!/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 root@192.168.74.15
;;
2)
;;
3)
menu1
read -p "请输入你要操作的内容:" actions
case $actions in
1)
ssh root@192.168.74.15
echo "日志正在清理中!"
;;
2)
ssh root@192.168.74.15
systemctl start httpd
;;
3)
ssh root@192.168.74.15
systemctl restart httpd
;;
h)
menu1
;;
*)
echo "请选择您要操作的主机:"
;;
esac
menu
;;
4)
;;
h)
menu
;;
q)
exit
;;
esac
done
以上是关于shell之循环嵌套与扩展(函数)的主要内容,如果未能解决你的问题,请参考以下文章