3.Shell编程之循环语句

前言

循环语句,自动化处理重复任务的利器。for循环擅长处理预定义的列表,如批量创建用户账号;while循环更适用于需要按特定条件重复执行操作的场景;until循环则与while循环相反,在条件为假时执行循环体。

一:for循环语句

实际工作中,经常会遇到某项任务的情况,而再次执行时仅仅是处理的对象不一样,其他命令相同。例如,根据通讯录中的姓名列表创建系统账号,根据服务器清单检查各主机的存活状态,根据IP地址黑名单设置拒绝访问的防火墙策略。

当面对各种列表重复任务时,使用简单的if语句已经难以满足要求,而顺序编写全部代码更是显得异常烦琐、困难重重。

1:for语句的结构

使用for循环语句时,需要指定一个变量及可能的取值列表,针对每个不同的取值重复执行相同的命令序列,直到变量值用完退出循环。在这里,“取值列表”称为for语句的执行条件,其中包括多个属性相同的对象,需要预先指定(如通讯录、IP黑名单)

语法结构如下:

for  变量名  in  取值列表

do

      命令序列

done

for语句的操作对象为用户指定名称的变量,并通过in关键字为该变量预先设置了一个取值列表,多个取值之间以空格进行分隔。位于do...done之间的命令序列称为循环体,其中的执行语句需要引用变量以完成相应的任务。

执行流程:首先将列表中的第一个取值赋给变量,并执行do...done循环体中的命令序列;然后将列表中的第二个取值赋给变量,并执行循环体中的命令序列,以此类推,直到表中的所有取值用完,最后跳至done语句,表示循环结束。

2:for语句应用示例

(1)根据姓名列表批量添加用户

根据人事部门给出的员工姓名的拼音列表,在Linux服务器中添加相应的用户账号,初始密码均设置为“123456”.其中,员工姓名列表中的账号数量不固定,而且除了要求账号名称是拼音之外,并无其他特殊规律。

针对上述要求,可先指定员工列表文件users.txt,然后编写一个名为uaddfor.sh的Shell脚本,从users.txt文件中读取各用户名称,重复执行添加用户、设置初始密码的相关操作。

命令:vim  /root/users.txt          (用于测试的列表文件)

chenye

dengchao

zhangjie

            vim  uaddfor.sh                 (批量添加用户的脚本)

#!/bin/bash

ULIST=$(cat  /root/users.txt)

for  UNAME  in  $ULIST

do 

               useradd  $UNAME

               echo  "123456"  |  passwd  --stdin  $UNAME  &>/dev/null

done

           chmod  +x  uaddfor.sh

           ./uaddfor.sh                             (测试并确认执行结果)

若要删除uaddfor.sh脚本所添加的用户,只需要参考上述脚本代码,将for循环体中添加用户的命令序列改为删除用户的操作即可。

命令:vim  udelfor.sh                             (批量删除用户的脚本)

#!/bin/bash

ULIST=$(cat  /root/users.txt)

for  UNAME  in  $ULIST

do 

              userdel  -r  $UNAME  &>/dev/null

done

           chmod  +x  udelfor.sh

           ./udelfor.sh                                      (测试并确认结果)

           id  chenye                                     (将提示无此用户)

(2)根据IP地址列表检查主机状态

根据包含公司各服务器IP地址的列表文件,检查其中各主机的ping连通性,输出各主机是否启动、关闭。其中,服务器数量并不固定,各服务器的IP地址之间也无特殊规律

针对此案例要求,可先指定IP地址列表文件ipadds.txt,然后编写一个名为chkhosts.sh的Shell脚本,从ipadds.txt文件中读取各服务器的IP地址,重复执行平连通测试,并根据测试结果输出相应的提示信息

命令:vim  /root/ipadds.txt

172.16.16.1

172.16.16.22

172.16.16.220

           vim  chkhosts.sh                           (循环检查各主机的脚本)

#!/bin/bash

HLIST=$(cat  /root/ipadds.txt)

         for  IP  in  $HLIST

do 

         ping  -c 3 -i 0.2 -w 3 $IP  &>  /dev/null (-c:发送包的数量  -i发送ping包间隔  -w超时时间)

if  [  $?  -eq  0  ]

then

          echo  "Host  $IP  is  up."

else

          echo  "Host  $IP  is  down."

fi

done

           chmod  +x  chkhosts.sh

           ./chkhosts.sh

二:使用while循环语句

for循环语句非常适用于列表对象无规律,且列表来源已固定(如某个列表文件)的场合。而对于要求控制循环次数、操作对象按数字顺序编号、按特定条件执行重复操作等情况,则更适合使用另外一种循环——while语句

1:while语句的结构

使用while循环语句时,可以根据特定条件反复执行一个命令序列,直到该条件不再满足时为止。在脚本应用中,应该避免出现死循环的情况,否则后边的命令操作将无法执行。因此,循环体内的命令序列中应包括修改测试条件的语句,以便在适当的时候使测试条件不再成立,从未结束循环。

语法结构:

while  条件测试操作

do

       命令序列

done

执行流程:首先判断while后的条件测试操作结果,如成立,则执行do...done循环体中的命令序列:返回while后再次判断条件测试结果,如果条件仍然成立,则继续执行执行循环体:再次返回到while后,判断条件测试结果,如此循环,直到while后的条件测试结果不再成立为止,最后跳转到done语句,表示结束循环

使用while循环语句时,有两个特殊条件测试操作,即true(真)和false(假)。true作为条件时,表示条件永远成立,循环体内的命令序列将无限执行下去,除非强制终止脚本(或通过exit语句退出脚本);反之,若使用false作为条件,则循环体将不会被执行。

2:while语句应用示例

(1)批量添加规律编号的用户

在一些技术培训和学习领域,出于实验或测试目的,需要批量添加用户账号,这些用户的名称中包含固定的前缀字串,并按照数字顺序依次进行编号,账号的数量往往是固定的。例如,若要添加20个用户,名称依次为stu1、stu2、....、stu20

命令:vim  uaddwhile.sh

#!/bin/bash

PREFIX="stu"

i=1

while  [  $i  -le  20  ]

do 

          useradd  ${PREFIX}$i

          echo  "123456"  |  passwd  --stdin  ${PREFIX}$i  &>  /dev/null

          let  i++

done

           chmod  +x  uaddwhile.sh

若要删除uaddwhile.sh脚本所添加的用户,只需要参考上述脚本代码,将while循环体中添加用户的命令序列改为删除用户的操作即可

命令:vim  udelwhile.sh

#!/bin/bash

PREFIX="stu"

i=1

while  [  $i  -le  20  ]

do 

        userdel  -r  ${PREFIX}$i

done

           chmod  +x  udelwhile.sh

           ./udelwhile.sh

           id  stu20                                  (提示无此用户)

(2)猜价格游戏

案例要求如下:由脚本预先生成一个随机的价格数目(~999)作为实际价格,判断用户猜测的价格是否高出或低于实际价格,给出相应提示后再次要求用户猜测;一直到用户猜中实际价格为止,输出用户共猜测的次数、实际价格。
针对上述要求,主要设计思路如下:通过环境变量RANDOM可获得一个小于216的随机整数,计算其与1000的余数即可获得~999的随机价格;反复猜测操作可以通过以true作为测试条件的while 循环实现,当用户猜中实际价格时终止循环;判断猜测价格与实际价格的过程采用 if 语句实现嵌套在 while 循环体内;使用变量来记录猜测次数:
命令:vim pricegame.sh
#!/bin/bash
PRICE=$(expr  $RANDOM  % 1000)
TIMES=0
echo  “商品实际价格范围为0-999,猜猜看是多少?"
while  true
do
          read-p  "请输入你猜测的价格数目:"INT
          let  TIMES++
          if  [  $INT  -eq  $PRICE  ]
          then
                 echo  "恭喜你答对了,实际价格是$PRICE"
                 echo  "你总共猜测了$TIMES次"
                 exit 0
         elif  [  $INT  -gt  $PRICE  ]
then
                  echo  "太高了!"
      else

                  echo  "太低了!"

        fi

done

           chmod  +x  pricegame.sh

           ./pricegame.sh

三:until循环语句

1:until语句结构

unti1 循环与 while循环类似,while 循环能实现的脚本 unti1 同样也可以实现,但区别是while循环在条件为真是继续执行循环,而unti1则是在条件为假时执行循环。
unti1 循环语句的语法结构:
until 条件测试操作
do
    命令序列
done
unti1 语句的执行流程:首先判断 unti1 后的条件测试操作结果,如果条件不成立,则执行 do..done循环体中的命令序列;返回unti1后再次判断条件测试结果,如果条件仍然不成立,则继续执行循环体;再次返回到 unti1 后,判断条件测试结果…如此循环,直到unti1后的条件测试结果成立为止,最后跳转到 done 语句,表示结束循环。

2:until语句应用示例

(1)计算1~50的和

计算从1到50的和,从1开始相加,采用循环的方式,每次循环后加1,将得到的值加入计算的和中,数字运算采用的是let方式,直到加到50为止,具体的操作参考如下,
命令:vim  sum1to50_ until_ v1.sh
#!/bin/bash
i=0;s=0
until  [  $i  -eq  50  ]

do
       let  "i=$i+1";let "s=$s+$i"  done
       echo  'sum(1..50)='$s

           chmod +x sumlto50 until v1.sh

           ./sum1to50_ until_ v1.sh

上述代码中,在i的值小于50 之前,每次循环i的值加1,并且求出s的值。

(2)为指定用户发送在线消息

公司内部有一台Linux测试服务器,开发、测试、运维都在使用自己的账号连接登录到服务器上。当业务增加不能满足使用需求时,运维决定给服务器增加内存配置,要通知开发和测试人员保存数据退出,之后再关机升级内存,以应对业务的增加。
针对上面的需求,可编写一个名字为unti1-useronline_to_write.sh的 She1l 脚本,用于给已登录用户发送消息,对用户进行检测,必须是系统内用户并且处于登录状态,通过Linux的 write 命令来发送消息,具体的脚本如下所示。
命令:vim until-user online to write.sh
#!/bin/bash
if  [  $#  -lt   2  ]; then                            ( 检查参数数量是否足够)

             echo   "Usage: $0 <username1><username2>...<message>"

            exit 1
fi
message="${!#}"                                      (提取消息,消息为最后一个参数)

for username in  "${@:1:$#-1}"; do         (遍历除最后一个参数外的所有用户名)

if  !  grep  -q  "^$username:" /etc/passwd; then

           echo  "$username is not a valid usen on this system."

           continue                          (检查用户是否为系统内用户)
fi

while  !  who  |  grep  -q  "$username”; do

          echo  "$username is not logged on. Waiting for the user to log in..."

          sleep 60
done                                              (持续检查用户是否登录)
#用户已登录,发送消息
          echo  "Sending message to $username..."(用户已登录,发送消息)

          write  "$username" <<EOF

$message
EOF
         if  [  $?  -ne  0  ]; then
                    echo "Failed to send message to $username."
     fi
done

                  chmod +x until-user online to write.sh

               ./until-user_online to_write.sh root

               ./until-user online to write.sh root hello(发给root 自己,消息为“hello”)
               ./until-user online to write.sh jerry hello(发给用户 jerry,消息为“hello”)
               ./until-user online to write.sh jerry        (发给用户 jerry,消息为空)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值