一、当型和直到型循环

1.while循环语句

  1. while < 条件表达式 >
  2. do
  3. 指令...
  4. done

while循环执行流程对应的逻辑图

2.until循环语句

  1. until < 条件表达式 >
  2. do
  3. 指令...
  4. done

until会在条件表达式不成立时,进入循环体执行指令。

3.基本范例

(1)每隔2秒输出一次系统负载

  1. [root@codis-178 ~]# cat 10_1.sh
  2. #!/bin/bash
  3. while true
  4. do
  5. uptime
  6. sleep 2
  7. done
  8. [root@codis-178 ~]# sh 10_1.sh
  9. 13:59:41 up 251 days, 22:33, 1 user, load average: 0.02, 0.03, 0.00
  10. 13:59:43 up 251 days, 22:33, 1 user, load average: 0.02, 0.03, 0.00
  11. 13:59:45 up 251 days, 22:33, 1 user, load average: 0.02, 0.03, 0.00
  12. 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

  1. [root@codis-178 ~]# cat 10_2.sh
  2. #!/bin/bash
  3. i=5
  4. while ((i>0))
  5. do
  6. echo "$i"
  7. ((i--))
  8. done
  9. [root@codis-178 ~]# sh 10_2.sh
  10. 5
  11. 4
  12. 3
  13. 2
  14. 1

(4)计算1加到100之和

  1. [root@codis-178 ~]# cat 10_3.sh
  2. #!/bin/bash
  3. i=1
  4. sum=0
  5. while ((i<=100))
  6. do
  7. ((sum=sum+i))
  8. ((i++))
  9. done
  10. [ "$sum" -ne 0 ] && printf "totalsum is:$sum\n"
  11. [root@codis-178 ~]# sh 10_3.sh
  12. totalsum is:5050

(5)猜数字,系统随机生成一个数字(1~60),让用户输入所猜数字,判断是否正确

  1. [root@codis-178 ~]# cat 10_4.sh
  2. #!/bin/bash
  3. total=0
  4. export LANG="zh_CN.UTF-8"
  5. NUM=$((RANDOM%61))
  6. echo "当前苹果的价格是每斤 $NUM 元"
  7. echo "============================"
  8. usleep 1000000
  9. clear
  10. echo "这苹果多少钱一斤啊?请猜0~60的数字"
  11. apple(){
  12. read -p "请输入你的价格:" PRICE
  13. expr $PRICE + 1 &>/dev/null
  14. if [ $? -ne 0 ];then
  15. echo "快猜数字!"
  16. apple
  17. fi
  18. }
  19. guess(){
  20. ((total++))
  21. if [ $PRICE -eq $NUM ]
  22. then
  23. echo "猜对了"
  24. if [ $total -le 3 ];then
  25. echo "已经猜 $total 次了!"
  26. elif [ $total -gt 3 -a $toatl -le 6 ];then
  27. echo "已经猜 $total 次了!"
  28. elif [ $total -gt 6 ];then
  29. echo "已经猜 $total 次了!有点多!"
  30. fi
  31. exit 0
  32. elif [ $PRICE -gt $NUM ];then
  33. echo "猜高了!"
  34. apple
  35. elif [ $PRICE -lt $NUM ];then
  36. echo "猜低了!"
  37. apple
  38. fi
  39. }
  40. main(){
  41. apple
  42. while true
  43. do
  44. guess
  45. done
  46. }
  47. main
  48. [root@codis-178 ~]# sh 10_4.sh
  49. 当前苹果的价格是每斤 30
  50. ============================
  51. 这苹果多少钱一斤啊?请猜0~60的数字
  52. 请输入你的价格:40
  53. 猜高了!
  54. 请输入你的价格:25
  55. 猜低了!
  56. 请输入你的价格:30
  57. 猜对了
  58. 已经猜 3 次了!

(6)手机充值10元,每发一条短信花费1.5元,当余额低于1.5元时不能再发短信

  1. [root@codis-178 ~]# cat 10_5.sh
  2. #!/bin/bash
  3. export LANG="zh_CN.UTF-8"
  4. sum=15
  5. msg_fee=2
  6. msg_count=0
  7. menu(){
  8. cat <<END
  9. 当前余额为 ${sum} 分,每条短信需要 ${msg_fee}
  10. =================================
  11. 1. 充值
  12. 2. 发消息
  13. 3. 退出
  14. ================================
  15. END
  16. }
  17. recharge(){
  18. read -p "请输入充值金额:" money
  19. expr $money + 1 &>/dev/null
  20. if [ $? -ne 0 ];then
  21. echo "then money your input is error,must be int."
  22. else
  23. sum=$(($sum+$money))
  24. echo "当前余额为:$sum"
  25. fi
  26. }
  27. sendInfo(){
  28. if [ ${sum} -lt ${msg_fee} ];then
  29. printf "余额不足:$sum,请充值。\n"
  30. else
  31. while true
  32. do
  33. read -p "请输入短信内容:" msg
  34. sum=$(($sum-$msg_fee))
  35. printf "发送 $msg successfully!\n"
  36. printf "当前余额:$sum\n"
  37. if [ $sum -lt $msg_fee ];then
  38. printf "余额不足,剩余 $sum分\n"
  39. return 1
  40. fi
  41. done
  42. fi
  43. }
  44. main(){
  45. while true
  46. do
  47. menu
  48. read -p "请输入数字选择:" men
  49. case "$men" in
  50. 1)
  51. recharge
  52. ;;
  53. 2)
  54. sendInfo
  55. ;;
  56. 3)
  57. exit 1
  58. ;;
  59. *)
  60. printf "选择错误,必须是{1|2|3}\n"
  61. esac
  62. done
  63. }
  64. main

4.企业应用

(1)监控网站,每隔10秒确定一次网站是否正常

  1. [root@codis-178 ~]# cat 10_6.sh
  2. #!/bin/bash
  3. . /etc/init.d/functions
  4. check_count=0
  5. url_list=(
  6. http://www.baidu.com
  7. http://www.anzhi.com
  8. http://www.163.com
  9. )
  10. function wait(){
  11. echo -n '3秒后,执行检查URL操作。';
  12. for ((i=0;i<3;i++))
  13. do
  14. echo -n ".";sleep 1
  15. done
  16. echo
  17. }
  18. function check_url(){
  19. wait
  20. for ((i=0; i<`echo ${#url_list[*]}`; i++))
  21. do
  22. wget -o /dev/null -T 3 --tries=1 --spider ${url_list[$i]} >/dev/null 2>&1
  23. if [ $? -eq 0 ];then
  24. action "${url_list[$i]}" /bin/true
  25. else
  26. action "${url_list[$i]}" /bin/false
  27. fi
  28. done
  29. ((check_count++))
  30. }
  31. main(){
  32. while true
  33. do
  34. check_url
  35. echo "-------check count:${check_count}--------"
  36. sleep 5
  37. done
  38. }
  39. main
  40. [root@codis-178 ~]# sh 10_6.sh
  41. 3秒后,执行检查URL操作。...
  42. http://www.baidu.com [ OK ]
  43. http://www.anzhi.com [ OK ]
  44. http://www.163.com [ OK ]
  45. -------check count:1--------
  46. 3秒后,执行检查URL操作。...
  47. http://www.baidu.com [ OK ]
  48. http://www.anzhi.com [ OK ]
  49. http://www.163.com [ OK ]
  50. -------check count:2--------

(2)分析Apache日志,把日志中每行的访问字节数对应的字段数字相加,计算总的访问量。

  1. [root@codis-178 ~]# cat 10_7.sh
  2. #!/bin/bash
  3. sum=0
  4. exec <$1 #将参数$1输入重定向给exec
  5. while read line
  6. do
  7. size=`echo $line|awk '{print $10}'`
  8. expr $size + 1 &>/dev/null
  9. if [ $? -ne 0 ];then
  10. continue
  11. fi
  12. ((sum=sum+$size))
  13. done
  14. echo "${1}:total:${sum}bytes = `echo $((${sum}/1024))`KB}"

一条命令完成

  1. awk '{print $10}' access.log |grep -v "-"|awk '{sum+=$1}END{print sum}'

5.按行读文件的方法总结

(1)exec

  1. exec <FILE
  2. sum=0
  3. while read line
  4. do
  5. cmd
  6. done

(2)cat

  1. cat FILE|while read line
  2. do
  3. cmd
  4. done

(3)在while循环结尾

  1. while read line
  2. do
  3. cmd
  4. done < FILE

6.实战应用

根据Web日志或系统网络连接数,监控某个IP的并发连接数,若短时间内PV达到100,即调用防火墙命令封掉对应的IP。

(1)按日志分析

  1. [root@codis-178 ~]# cat 10_8.sh
  2. #!/bin/bash
  3. file=$1
  4. while true
  5. do
  6. awk '{print $1}' $1|grep -v "^$"|sort|uniq -c > /tmp/tmp.log
  7. exec </tmp/tmp.log
  8. while read line
  9. do
  10. ip=`echo $line|awk '{print $2}'`
  11. count=`echo $line|awk '{print $1}'`
  12. if [ $count -gt 500 ] && [ `iptables -L -n|grep "$ip"|wc -l` -lt 1 ];then
  13. iptables -I INPUT -s $ip -j DROP
  14. echo "$line is dropped" >>/tmp/droplist_$(date +%F).log
  15. fi
  16. done
  17. sleep 10
  18. done

(2)按TCP请求

  1. [root@codis-178 ~]# cat 10_9.sh
  2. #!/bin/bash
  3. file=$1
  4. JudgeExt(){
  5. if expr "$1" : ".*\.log" &>/dev/null
  6. then
  7. :
  8. else
  9. echo $"usage:$0 xxx.log"
  10. exit 1
  11. fi
  12. }
  13. IpCount(){
  14. 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
  15. }
  16. ipt(){
  17. local ip=$1
  18. if [ `iptables -L -n|grep "$ip"|wc -l` -lt 1 ];then
  19. iptables -I INPUT -s $ip -j DROP
  20. echo "$line is dropped" >>/tmp/droplist_$(date +%F).log
  21. fi
  22. }
  23. main(){
  24. JudgeExt $file
  25. while true
  26. do
  27. IpCount $file
  28. while read line
  29. do
  30. ip=`echo $line|awk '{print $2}'`
  31. count=`echo $line|awk '{print $1}'`
  32. if [ $count -gt 3 ];then
  33. ipt $ip
  34. fi
  35. done</tmp/tmp.log
  36. done
  37. }
  38. main

Shell编程之while循环和until循环的更多相关文章

  1. shell编程之awk命令详解

    shell编程之awk命令详解 a:focus { outline: thin dotted #333; outline: 5px auto -webkit-focus-ring-color; out ...

  2. 03 shell编程之case语句与函数

    本文所有内容均来自当年博主当年学习笔记,若有不足欢迎指正 Shell编程之case语句与函数 学习目标: 掌握case语句编程 掌握shell函数的使用 目录结构: Case语句 Case语句的作用 ...

  3. shell编程之case分支语句

    shell编程之case分支语句 case分支语句和if的多分支语句很相似. if多分支语句一般用在有(区间范围)的地方 :例如:0-100之间. if需要判断多个不同的条件. case的分支语句用在 ...

  4. shell编程之if语句

    shell编程之if判断 目录 shell编程之if判断 1.整数比较 2.字符串比较 3.举例 1.数字比较 2.字符串比较 4.Other 1.整数比较 -eq 等于,如:if [ "$ ...

  5. shell 编程之 for while until 循环

    shell 的for循环 的格式如下: for 变量  in 列表 do ... done 列表是一组值的序列 每个值通过空格隔开 每循环一次,列表中的下一个值赋给变量 in 列表是可选的,如果不用他 ...

  6. Shell编程之for和select循环

    一.for和select循环 1.for循环语法 for 变量名 in 变量取值列表 do 指令... done C语言型for循环 for ((exp1; exp2; exp3)) do 指令... ...

  7. shell编程之BASH变量(2)

    变量命名规范 在bash中,变量的默认类型都是字符串型,定义 name = 'kk' 变量分类 用户自定义变量.变量自定义的 环境变量:这种变量中主要保存的是和系统操作环境相关的数据.变量可以自定义, ...

  8. shell编程之99乘法表

    #99乘法表#!/bin/bash #第一种写法 ` #`seq ` 使用反撇号括起来的(不是单引号),表示命令替换 do for j in `seq $i` #seq可以使用变量 do echo - ...

  9. Shell编程之Shift的用法

    位置参数可以用shift命令左移.比如shift 3表示原来的$4现在变成$1,原来的$5现在变成$2等等,原来的$1.$2.$3丢弃,$0不移动.不带参数的shift命令相当于shift 1. 非常 ...

随机推荐

  1. Android.mk解析

    https://developer.android.com/ndk/guides/android_mk.html#over LOCAL_STATIC_LIBRARIES PREBUILT_STATIC ...

  2. Hibernate无主键配置文件编写

    1.       环境:jdk1.4+hibernate2.0+weblogic8 一般情况下,我们建的表都会有主键,然后根据hibernate的配置文件编写条件 有一个主键key,剩下的是Prope ...

  3. crm操作电子邮件

    using System;     using Microsoft.Xrm.Sdk;     using Microsoft.Crm.Sdk.Messages;     using Microsoft ...

  4. go语言递归创建目录

    import ( "fmt" "os" ) func main() { //创建C:/temp/log文件夹 // err := os.MkdirAll(&qu ...

  5. Type Group(类型组)

    在 APAP 程序开发中, 经常需要定义一些常量或变量, 而且可能存在多个程序中需要用到的类似的变量或结构体, SAP 提供了类型组, 允许用户建立一些公用的对象, 允许在不同的程序中调用, 这样不但 ...

  6. Quartz.NET 作业调度

    Quartz 简介: Quartz.NET是一个开源的作业调度框架,非常适合在平时的工作中,定时轮询数据库同步,定时邮件通知,定时处理数据等. Quartz.NET允许开发人员根据时间间隔(或天)来调 ...

  7. Andriod - 创建自定义控件

    控件和布局的继承结构: 可以看到,我们所用的所有控件都是直接或间接继承自 View的,所用的所有布局都是直接或间接继承自 ViewGroup 的.View 是 Android 中一种最基本的 UI 组 ...

  8. Splay_Tree 模板(区间修改,旋转操作)

    1.旋转操作 #define MAXN 100100 bool Add[MAXN];//延迟标记 struct Splay_Tree { int cnt, rt;//cnt为节点数,rt == roo ...

  9. 【BZOJ2286】[Sdoi2011]消耗战 虚树

    [BZOJ2286][Sdoi2011]消耗战 Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的 ...

  10. inner join和out join的区别

    inner join(又叫join) out join包括left join,right join和full join(也就是left+right)