一、当型和直到型循环
1.while循环语句
while < 条件表达式 > do 指令... done
while循环执行流程对应的逻辑图
2.until循环语句
until < 条件表达式 > do 指令... done
until会在条件表达式不成立时,进入循环体执行指令。
3.基本范例
(1)每隔2秒输出一次系统负载
[root@codis-178 ~]# cat 10_1.sh #!/bin/bash while true do uptime sleep 2 done [root@codis-178 ~]# sh 10_1.sh 13:59:41 up 251 days, 22:33, 1 user, load average: 0.02, 0.03, 0.00 13:59:43 up 251 days, 22:33, 1 user, load average: 0.02, 0.03, 0.00 13:59:45 up 251 days, 22:33, 1 user, load average: 0.02, 0.03, 0.00 13:59:47 up 251 days, 22:33, 1 user, load average: 0.02, 0.03, 0.00
(2)防止脚本执行中断的办法
1)使用&,在后台运行
2)使用nohup加&,在后台运行
3)利用screen保持会话,然后再执行命令或脚本
补充;
strace:跟踪一个进程的系统调用情况
ltrace:跟踪进程调用库函数的情况
(3)while循环竖向打印54321
[root@codis-178 ~]# cat 10_2.sh #!/bin/bash i=5 while ((i>0)) do echo "$i" ((i--)) done [root@codis-178 ~]# sh 10_2.sh 5 4 3 2 1
(4)计算1加到100之和
[root@codis-178 ~]# cat 10_3.sh #!/bin/bash i=1 sum=0 while ((i<=100)) do ((sum=sum+i)) ((i++)) done [ "$sum" -ne 0 ] && printf "totalsum is:$sum\n" [root@codis-178 ~]# sh 10_3.sh totalsum is:5050
(5)猜数字,系统随机生成一个数字(1~60),让用户输入所猜数字,判断是否正确
[root@codis-178 ~]# cat 10_4.sh #!/bin/bash total=0 export LANG="zh_CN.UTF-8" NUM=$((RANDOM%61)) echo "当前苹果的价格是每斤 $NUM 元" echo "============================" usleep 1000000 clear echo "这苹果多少钱一斤啊?请猜0~60的数字" apple(){ read -p "请输入你的价格:" PRICE expr $PRICE + 1 &>/dev/null if [ $? -ne 0 ];then echo "快猜数字!" apple fi } guess(){ ((total++)) if [ $PRICE -eq $NUM ] then echo "猜对了" if [ $total -le 3 ];then echo "已经猜 $total 次了!" elif [ $total -gt 3 -a $toatl -le 6 ];then echo "已经猜 $total 次了!" elif [ $total -gt 6 ];then echo "已经猜 $total 次了!有点多!" fi exit 0 elif [ $PRICE -gt $NUM ];then echo "猜高了!" apple elif [ $PRICE -lt $NUM ];then echo "猜低了!" apple fi } main(){ apple while true do guess done } main [root@codis-178 ~]# sh 10_4.sh 当前苹果的价格是每斤 30 元 ============================ 这苹果多少钱一斤啊?请猜0~60的数字 请输入你的价格:40 猜高了! 请输入你的价格:25 猜低了! 请输入你的价格:30 猜对了 已经猜 3 次了!
(6)手机充值10元,每发一条短信花费1.5元,当余额低于1.5元时不能再发短信
[root@codis-178 ~]# cat 10_5.sh #!/bin/bash export LANG="zh_CN.UTF-8" sum=15 msg_fee=2 msg_count=0 menu(){ cat <<END 当前余额为 ${sum} 分,每条短信需要 ${msg_fee} 分 ================================= 1. 充值 2. 发消息 3. 退出 ================================ END } recharge(){ read -p "请输入充值金额:" money expr $money + 1 &>/dev/null if [ $? -ne 0 ];then echo "then money your input is error,must be int." else sum=$(($sum+$money)) echo "当前余额为:$sum" fi } sendInfo(){ if [ ${sum} -lt ${msg_fee} ];then printf "余额不足:$sum,请充值。\n" else while true do read -p "请输入短信内容:" msg sum=$(($sum-$msg_fee)) printf "发送 $msg successfully!\n" printf "当前余额:$sum\n" if [ $sum -lt $msg_fee ];then printf "余额不足,剩余 $sum分\n" return 1 fi done fi } main(){ while true do menu read -p "请输入数字选择:" men case "$men" in 1) recharge ;; 2) sendInfo ;; 3) exit 1 ;; *) printf "选择错误,必须是{1|2|3}\n" esac done } main
4.企业应用
(1)监控网站,每隔10秒确定一次网站是否正常
[root@codis-178 ~]# cat 10_6.sh #!/bin/bash . /etc/init.d/functions check_count=0 url_list=( http://www.baidu.com http://www.anzhi.com http://www.163.com ) function wait(){ echo -n '3秒后,执行检查URL操作。'; for ((i=0;i<3;i++)) do echo -n ".";sleep 1 done echo } function check_url(){ wait for ((i=0; i<`echo ${#url_list[*]}`; i++)) do wget -o /dev/null -T 3 --tries=1 --spider ${url_list[$i]} >/dev/null 2>&1 if [ $? -eq 0 ];then action "${url_list[$i]}" /bin/true else action "${url_list[$i]}" /bin/false fi done ((check_count++)) } main(){ while true do check_url echo "-------check count:${check_count}--------" sleep 5 done } main [root@codis-178 ~]# sh 10_6.sh 3秒后,执行检查URL操作。... http://www.baidu.com [ OK ] http://www.anzhi.com [ OK ] http://www.163.com [ OK ] -------check count:1-------- 3秒后,执行检查URL操作。... http://www.baidu.com [ OK ] http://www.anzhi.com [ OK ] http://www.163.com [ OK ] -------check count:2--------
(2)分析Apache日志,把日志中每行的访问字节数对应的字段数字相加,计算总的访问量。
[root@codis-178 ~]# cat 10_7.sh #!/bin/bash sum=0 exec <$1 #将参数$1输入重定向给exec while read line do size=`echo $line|awk '{print $10}'` expr $size + 1 &>/dev/null if [ $? -ne 0 ];then continue fi ((sum=sum+$size)) done echo "${1}:total:${sum}bytes = `echo $((${sum}/1024))`KB}"
一条命令完成
awk '{print $10}' access.log |grep -v "-"|awk '{sum+=$1}END{print sum}'
5.按行读文件的方法总结
(1)exec
exec <FILE sum=0 while read line do cmd done
(2)cat
cat FILE|while read line do cmd done
(3)在while循环结尾
while read line do cmd done < FILE
6.实战应用
根据Web日志或系统网络连接数,监控某个IP的并发连接数,若短时间内PV达到100,即调用防火墙命令封掉对应的IP。
(1)按日志分析
[root@codis-178 ~]# cat 10_8.sh #!/bin/bash file=$1 while true do awk '{print $1}' $1|grep -v "^$"|sort|uniq -c > /tmp/tmp.log exec </tmp/tmp.log while read line do ip=`echo $line|awk '{print $2}'` count=`echo $line|awk '{print $1}'` if [ $count -gt 500 ] && [ `iptables -L -n|grep "$ip"|wc -l` -lt 1 ];then iptables -I INPUT -s $ip -j DROP echo "$line is dropped" >>/tmp/droplist_$(date +%F).log fi done sleep 10 done
(2)按TCP请求
[root@codis-178 ~]# cat 10_9.sh #!/bin/bash file=$1 JudgeExt(){ if expr "$1" : ".*\.log" &>/dev/null then : else echo $"usage:$0 xxx.log" exit 1 fi } IpCount(){ grep "ESTABLISHED" $1 |awk -F "[ :]+" '{ ++S[$(NF-3)]}END {for(key in S) print S[key], key}'|sort -rn -k1|head -5 >/tmp/tmp.log } ipt(){ local ip=$1 if [ `iptables -L -n|grep "$ip"|wc -l` -lt 1 ];then iptables -I INPUT -s $ip -j DROP echo "$line is dropped" >>/tmp/droplist_$(date +%F).log fi } main(){ JudgeExt $file while true do IpCount $file while read line do ip=`echo $line|awk '{print $2}'` count=`echo $line|awk '{print $1}'` if [ $count -gt 3 ];then ipt $ip fi done</tmp/tmp.log done } main
来源:https://www.cnblogs.com/tongxiaoda/p/7454640.html