前言:当面对各种列表重复任务时,使用if语句已经难以满足要求,而顺序编写全部代码更是显得异常繁琐,困难重重。使用循环、分支等其他程序控制结构,从而能够轻松完成更加复杂、强大的功能。 1、使用for循环语句 for语句结构: for 变量名 in 取值列表 do 命令序列 done for循环语句的结构: 1)根据姓名列表批量添加用户 准备员工列表文件users.txt,然后编写一个名为uaddfor.sh的脚本,从users.txt文件中读取各用户名称,重复执行添加用户,设置初始密码的相关操作。 [root@localhost ~]# vim /root/user.txt //用作测试的列表文件
chenpeng dengchao zhangjie 批量添加用户的脚本 [root@localhost ~]# vim uaddfor.sh
#!/bin/bash ulist=$(cat /root/user.txt) for uname in $ulist do useradd $uname echo "123456" | passwd --stdin $uname &> /dev/null done [root@localhost ~]# chmod +x uaddfor.sh //添加执行权限 [root@localhost ~]# ./uaddfor.sh //测试并确认执行结果 [root@localhost ~]# tail -3 /etc/passwd chenpeng:x:501:501::/home/chenpeng:/bin/bash dengchao:x:502:502::/home/dengchao:/bin/bash zhangjie:x:503:503::/home/zhangjie:/bin/bash 2)若要删除uaddfor.sh脚本添加的用户,只需要将上面脚本中添加用户的命令改为删除的即可。 [root@localhost ~]# cp uaddfor.sh udelfor.sh [root@localhost ~]# vim udelfor.sh //批量删除用户的脚本 #!/bin/bash ulist=$(cat /root/user.txt) for uname in $ulist do userdel $uname echo "123456" | passwd --stdin $uname &> /dev/null done [root@localhost ~]# chmod +x udelfor.sh [root@localhost ~]# ./udelfor.sh [root@localhost ~]# id chenpeng id: chenpeng:无此用户 执行脚本之后发现用户已经删除 3)根据ip地址列表查看主机状态 首先建立ip地址列表文件ipadds.txt,然后编写一个名为chkhosts.sh的shell脚本,从ipadds.txt文件中读取各服务器的ip地址,重复执行ping连通性测试,并根据测试结果输出相应的提示信息。 [root@localhost ~]# vim /root/ipadds.txt //用作测试的列表文件
192.168.1.1
192.168.1.2 192.168.1.10 [root@localhost ~]# 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 if [ $? -eq 0 ] then echo "host $ip is up" else echo "host $ip is down" fi done 执行脚本 [root@localhost /]# chmod +x chkhosts.sh [root@localhost /]# ./chkhosts.sh host 192.168.1.1 is up host 192.168.1.2 is down host 192.168.1.10 is down 2、使用while循环语句 For循环适合无规律,列表已固定,while循环适合要求循环次数,操作对象按数字顺序编号,按特定条件执行重复操作的情况。 while语句的语法结构: while 条件测试操作 do 命令序列 done while循环语句的结构: 1)批量添加规律编号的用户,添加20个用户,名称依次为stu1,stu2,... Stu20 [root@localhost /]# 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 [root@localhost /]# chmod +x uaddwhile.sh [root@localhost /]# ./uaddwhile.sh [root@localhost /]# grep "stu" /etc/passwd | tail -3 stu18:x:518:518::/home/stu18:/bin/bash stu19:x:519:519::/home/stu19:/bin/bash stu20:x:520:520::/home/stu20:/bin/bash 2)删除所添加的用户,只需将上述代码useradd修改成userdel即可 [root@localhost /]# cp uaddwhile.sh udelwhile.sh [root@localhost /]# vim udelwhile.sh #!/bin/bash prefix="stu" i=1 while [ $i -le 20 ] do userdel ${prefix}$i echo "123456" | passwd --stdin ${prefix}$i &> /dev/null let i++ done [root@localhost /]# chmod +x udelwhile.sh [root@localhost /]# ./udelwhile.sh [root@localhost /]# id stu20 id: stu20:无此用户 3)猜价格游戏 案例要求如下:由脚本预先生成一个随机的价格数目(0~999)作为实际价格,判断用户猜测的价格是否高出或低出实际价格,给出相应的提示够再次要求用户猜测;一直到用户猜中实际价格为止,输出用户共猜测的次数、实际价格。 思路:通过环境变量RANDOM可获得一个小于2的16次方的随机整数,计算其与1000的余数即可获得0-999的随机价格,反复猜测操作可以通过以true作为测试条件的while循环实现,当用户猜中实际价格时终止循环,判断猜测价格与实际价格的过程采用if语句实现,嵌套在while循环体内,使用变量来记录猜测次数。 [root@localhost /]# vim pricegame.sh
#!/bin/bash
price=$(expr $RANDOM % 1000) TIMES=0 echo "shangpin 0-999,ni cai?" while true do read -p "qing shu ru:" INT let TIMES++ if [ $INT -eq $price ] ; then echo "gongxi, jiageshi:$price" echo "ni cai le $TIMES ci" exit 0 elif [ $INT -gt $price ] ; then echo "taigaole" else echo "taidile" fi done [root@localhost /]# chmod +x pricegame.sh [root@localhost /]# ./pricegame.sh shangpin 0-999,ni cai? qing shu ru:500 taigaole qing shu ru:400 taidile qing shu ru:450 taidile qing shu ru:470 taigaole qing shu ru:469 taigaole qing shu ru:460 gongxi, jiageshi:460 ni cai le 6 ci 3、使用case分支语句 Case语句可以使用脚本程序的结构更加清晰。与if语句非常相似,只不过if语句需要判断多个不同的条件,而case语句只是判断一个变量的不同取值。 case分支语句的语法结构: case 变量值 in 模式1) 命令序列1 ;; 模式2) 命令序列2 ;; ...................... ) 默认命令序列 esac (是通配符,可匹配任意值) case分支语句的结构: 使用case分支语句时,需要注意: 1,case行尾必须为单词“in”,每一模式必须以右括号“)”结束 2,双分号“;;”表示命令序列的结束 3,模式字符串中,可以用方括号表示一个连续的范围,如【0-9】;还可以用竖杠符号“|”表示或,如“A|B” 4,最后的“)”表示默认模式,其中的相当于通配符 1)检查用户输入一个字符,通过case语句判断该字符是否为字母,数组或其他控制字符,并给出相应的提示信息。 [root@localhost /]# vim hitkey.sh
#!/bin/bash
read -p "qingshuru:" KEY case "$KEY" in [a-z] | [A-Z]) echo "ni shu ru de shi zimu" ;; [0-9]) echo "ni shu ru de shi shuzi" ;; *) echo "ni shu ru de shi qita" esac [root@localhost /]# chmod +x hitkey.sh [root@localhost /]# ./hitkey.sh qingshuru:z ni shu ru de shi zimu [root@localhost /]# ./hitkey.sh qingshuru:7 ni shu ru de shi shuzi [root@localhost /]# ./hitkey.sh qingshuru: / ni shu ru de shi qita 2)编写系统服务脚本 通过位置变量$1指定的start,stop,restart,status控制参数,分别用来启动、停止、重启sleep进程,以及查看sleep进程的状态。 [root@localhost /]# vim myprog
#!/bin/bash #chkconfig - 90 10 #description:aaaaaaaaaa case "$1" in start) echo -n "zhengzaiqidong sleep fuwu..." if sleep 7200 & //在后台启动sleep进程 then echo "ok" fi ;; stop) echo -n "zhengzaitingzhi sleep fuwu" pkill "sleep" &> /dev/null //杀死sleep进程 echo "ok" ;; status) if pgrep "sleep" &> /dev/null ; then //判断并提示sleep进程状态 echo "sleep fuwu yiqidong" else echo "sleep fuwu yitingzhi" fi ;; restart) //先停止,再启动服务 $0 stop $0 start ;; *) //默认显示用法信息 echo "yongfa: $0 {start|stop|status|restart}" esac [root@localhost /]# chmod +x myprog [root@localhost /]# ./myprog start zhengzaiqidong sleep fuwu...ok [root@localhost /]# ./myprog status sleep fuwu yiqidong [root@localhost /]# ./myprog stop zhengzaitingzhi sleep fuwuok [root@localhost /]# ./myprog reload //未提供此参数,按默认处理 yongfa: ./myprog {start|stop|status|restart}

然后执行下面的命令添加myprog为系统服务 [root@localhost /]# cp myprog /etc/init.d/