shell学习二十四–while循环

系统运维 waitig 475℃ 百度已收录 0评论

一、当型循环和直到型循环
当型循环结构:在每次执行循环体前,对条件进行判断,当条件满足时,执行循环体,否则终止循环。
直到型循环结构:在执行了一次循环体后,对条件进行判断,如果条件不满,就继续执行,知道条件满足终止循环。

Shell编程中循环命令用于特定条件下决定某些语句重复执行的控制方式,
有三种常用的循环语句:for、while和until。
while循环和for循环属于“当型循环”,而until属于“直到型循环”。
循环控制符:break和continue控制流程转向。

while 结构: 
while循环语句也称前测试循环语句,它的循环重复执行次数,是利用一个条件来控制是否继续重复执行这个语句。
while语句与for循环语句相比,无论是语法还是执行的流程,都比较简明易懂。while循环格式如下:
                   while 条件
                   do
                         command
                         command
                         …
                   done
while循环语句之所以命名为前测试循环,是因为它要先判断此循环的条件是否成立,然后才作重复执行的操作。也
就是说,while循环语句执行过程是:先判断expression的退出状态,如果退出状态为0,则执行循环体,并且在执
行完循环体后,进行下一次循环,否则退出循环执行done后的命令。
为了避免死循环,必须保证在循环体中包含循环出口条件,即存在expression的退出状态为非0的情况。

until(感觉和while相反)
先做,知道条件不满足才退出
until[condition-is-true]
do
       command..
done
应用场合不多,了解就好

二、实例
每隔两秒记录一次系统负载情况
sleep 1 休息1秒,usleep 1000000休息一秒
[root@node01 day11]# vi while01.sh
#!/bin/sh
while true
do 
  uptime
  sleep 2
done
[root@node01 day11]# sh while01.sh 
 13:46:06 up 5 days, 14:09,  4 users,  load average: 0.00, 0.00, 0.00
 13:46:08 up 5 days, 14:09,  4 users,  load average: 0.00, 0.00, 0.00
 13:46:10 up 5 days, 14:09,  4 users,  load average: 0.00, 0.00, 0.00
 
while true表示条件永远为真,因此会一直运行,像死循环一样,但是我们称呼为守护进程。

[root@node01 day11]# vi while01.sh
#!/bin/sh
while [ 1 ]
do 
  uptime >>./uptime.log
  usleep 1000000
done
[root@node01 day11]# sh while02.sh 
[root@node01 day11]# ls
uptime.log  while01.sh  while02.sh
[root@node01 day11]# cat uptime.log 
 14:00:26 up 5 days, 14:23,  4 users,  load average: 0.00, 0.00, 0.00
 14:00:27 up 5 days, 14:23,  4 users,  load average: 0.00, 0.00, 0.00
 如果使用&会在后台永久执行,这就是守护进程。
 
 [root@node01 day11]# vi while01.sh   这个放后台运行也会前台打印,所以加入到log文件
#!/bin/sh
while true
do
  uptime >>/var/log/uptime.log
  sleep 2
done
 
防止脚本执行中断的方法
1、sh while.sh &
2、screen  (保持会话)
3、nohup uptime.sh &

[root@node01 day11]# sh while01.sh  当已经执行了,但是没有放后台,又不想终止,先敲ctrl+z暂停
^Z
[1]+  Stopped                 sh while01.sh
[root@node01 day11]# bg             然后敲bg放入后台执行(fg放到前台)
[1]+ sh while01.sh &
[root@node01 day11]# sh while01.sh 
^Z
[2]+  Stopped                 sh while01.sh
[root@node01 day11]# bg  
[2]+ sh while01.sh &
[root@node01 day11]# jobs                列出job
[1]-  Running                 sh while01.sh &
[2]+  Running                 sh while01.sh &
[root@node01 day11]# fg 2                拿到前台    
sh while01.sh
[root@node01 day11]# jobs
[1]+  Running                 sh while01.sh &
[root@node01 day11]# fg 1
sh while01.sh
^C                                      终止
[root@node01 day11]# jobs
[root@node01 day11]# 

通过while循环计算1加到100之和(请用1+2+3的方法)
[root@node01 day11]# vi while03.sh 
#!/bin/sh
i=1
sum=0
while [ $i -le 100 ]              ============>((i < 101))也可以
do
  let sum=sum+i                                 ((sum=sum+i))
  let i=i+1                                      ((i++))
done
echo $sum
[root@node01 day11]# sh while03.sh 
5050
[root@node01 day11]# vi while04.sh 
#!/bin/sh
i=1
sum=0
while ((i < 101))
do
  ((sum=sum+i))
  ((i++))
done
echo $sum

[root@node01 day11]# cp while03.sh while05.sh
[root@node01 day11]# vi while05.sh 
#!/bin/sh
i=1
sum=0
while [ $i -le 5 ]
do
  let sum=sum+i
  let i=i+1
done
echo $sum
[root@node01 day11]# sh while05.sh 
15

用公式计算
[root@node01 day11]# vi sum01.sh
#!/bin/sh
((sum=10000000*(1+10000000)/2))
echo $sum
[root@node01 day11]# sh sum01.sh 
50000005000000
[root@node01 day11]# time sh sum01.sh 
50000005000000
real    0m0.004s
user    0m0.002s
sys     0m0.002s
[root@node01 day11]# vi while04.sh 
#!/bin/sh
i=1
sum=0
while ((i < 1000000))
do
  ((sum=sum+i))
  ((i++))
done
echo $sum
[root@node01 day11]# time sh while04.sh 
499999500000
real    0m6.885s
user    0m6.537s
sys     0m0.279s

使用while循环竖向打印10,9,8。。。1
[root@node01 day11]# vi while07.sh
#!/bin/sh
i=10
while ((i>0)) 
do
  echo $i
  let i=i-1
done
[root@node01 day11]# sh while07.sh 
10
9
8
7
6
5
4
3
2
1
[root@node01 day11]# vi while08.sh (打偶数)
#!/bin/sh
i=10
while ((i>0)) 
do
  echo $i
  let i=i-2
done
[root@node01 day11]# sh while08.sh           
10
8
6
4
2
[root@node01 day11]# vi while08.sh 
#!/bin/sh
i=9
while ((i>0)) 
do
  echo $i
  let i=i-2
done
[root@node01 day11]# sh while08.sh 
9
7
5
3
1

手机充值10远,每发一条短信话费(输出当前余额)1角5分,当余额低于1毛不能发短信,提示余额不足,请充值,请用while语句实现
[root@node01 day11]# vi while06.sh 
#!/bin/sh
i=15
sum=1000
while ((sum>=i))
do
  ((sum=sum-i))
  echo  "send message:$sum"
done
echo “money is not enough:$sum”
[root@node01 day11]# sh while06.sh  
send message,985
。。。。。
send message,70
send message,55
send message,40
send message,25
send message,10
“money is not enough:10”
[root@node01 day11]# 

实例分析apache日志例子
问题1:计算apache一天的log中所有行的log各元素访问字节数的综合,给出实现程序。
cat a.log|while readline
do

done
—————–
while read line
do

done<a.log
———-
exec <a.log
while read line
do

done
===========================
awk ‘{print $10}’ access_2010-12-8.log
head -1|awk ‘{print $10}’ access_2010-12-8.log

#!/bin/sh
sum=0
i=0
while read line
do
  i=$(echo $line|awk ‘{print $10}’) 
  if expr $i + 0&>/dev/null
     then
     ((sum=sum+i))
  fi
done<access_2010-12-8.log
echo $sum

例子:10秒钟做一次rsync binlog推送,守护进程方式,写完脚本后台执行。
#!/bin/sh
while true
do
    rsync -az /data/3306/mysql-bin* rsync_Backup@10.0.0.9::backup –password–file=/etc/rsync.password &
    sleep 10
done

/data/day11/rsync_binlog.sh &
echo "/data/day11/rsync_binlog.sh &">>/etc/rc.local

三、循环总结
1、while循环的特长是执行守护进程以及我们希望循环不退出继续执行,用于频率小于1分钟循环处理(大于1分钟一般用crontab)
,其他的while循环几乎都可以用for循环替代。
2、case语句可以if语句替换,一般在系统启动脚本传入少量固定规则字符串,用case,其他普通判断多用if。
3、一句话,if,for语句最常用,其次while(守护进程),case(服务启动脚本)

四、总结进程管理命令
bg:后台运行
fg:挂起程序
jobs:显示后台程序
kill、pkill、killall:杀掉进程
crontab:设置定时
ps:查看进程
pstree:显示进程树
top:显示进程
nice:改变优先权
nohup:用户退出系统之后继续工作
pgrep:查找匹配条件的进程
strace:跟踪一个进程的系统调用情况  这个很好用(一个进程特别高可以跟踪pid)
ltrace:跟踪进程调用库函数的情况
vmstat:报告虚拟内存统计信息


本文由【waitig】发表在等英博客
本文固定链接:shell学习二十四–while循环
欢迎关注本站官方公众号,每日都有干货分享!
等英博客官方公众号
点赞 (0)分享 (0)