Shell流程语句

1. shell流程控制

  流程控制是改变程序运行顺序的指令。linux shell有一套自己的流程控制语句,其中包括条件语句(if),循环语句(for,while),选择语句(case)。

2. if语句

  格式:if list; then list; [ elif list; then list; ] ... [ else list; ] fi

2.1  单分支

  if 条件表达式; then

  命令

  fi

[root@localhost ~]# vim test.sh
#!/bin/bash
if [ 1 -eq 1 ];then
        echo "yes"
fi
[root@localhost ~]# bash test.sh
yes

2.2 双分支 

  if 条件表达式; then

  命令

  else

  命令

  fi

#!/bin/bash
if [ 1 -eq 2 ];then
        echo "yes"
else
        echo "no"
fi
[root@localhost ~]# bash -x test.sh                     #-x,调试
+ '[' 1 -eq 2 ']'
+ echo no
no
#判断crond进程是否正在运行
[root@localhost ~]# ps aux | grep "grep"
root      11941  0.0  0.0 112648   956 pts/3    S+   20:30   0:00 grep --color=auto
[root@localhost ~]#vim cron_d.sh
#!/bin/bash
NAME=crond
NUM=$(ps aux | grep $NAME | grep -vc grep)
if [ $NUM -eq 1 ]; then
echo "$NAME running."
else
echo "$NAME is not running!"
fi
#检查主机是否在线
#!/bin/bash
if ping -c 1 192.168.1.1 &>/dev/null; then        #if可以直接对命令进行判断
echo "OK."
else
echo "NO!"
fi

 

2.3 多分支

  if 条件表达式; then

  命令

  elif 条件表达式; then

  命令

  else

  命令

  fi

#!/bin/bash
N=$1                                               # 接收用户输入参数
if [ $N -eq 3 ]; then
echo "eq 3"
elif [ $N -eq 5 ]; then
echo "eq 5"
elif [ $N -eq 8 ]; then
echo "eq 8"
else
echo "no"
fi


如果第一个条件符合就不再向下匹配。

在写脚本时先在命令测试,无误后再写入脚本

if语句实例:编写一个计算器,实现简单的加减乘除

  要求:

  请输入一个数字: 7

  请输入运算符:+

  请输入第二个数字:7

  7+7=14

[root@localhost ~]# vim count.sh
#!/bin/bash
read -p "请输入第一个数字:" num1
read -p "请输入运算符:" cha
read -p "请输入第二个数字:" num2
count (){
        echo "${num1}${cha}${num2}=$((${num1}${cha}${num2}))"
}
error () {
        echo "Usage:$0 {+|-|*|/|0-9}"
}
if  [ -n '$num1' -a -n '$hca' -a -n '$num2' ];then
        if [ "$cha" == "+" ];then
        count
        elif [ "$cha" == "-" ];then
        count
        elif [ "$cha" == "*" ];then
        count
        elif [ "$cha" == "/" ];then
        count
        else
        error
        fi
else
        echo '输入内容不能为空'
fi
:wq
[root@localhost ~]# bash count.sh
请输入第一个数字:8
请输入运算符:+
请输入第二个数字:2
8+2=10
[root@localhost ~]# bash count.sh
请输入第一个数字:8
请输入运算符:*
请输入第二个数字:10
8*10=80
[root@localhost ~]# bash count.sh
请输入第一个数字:l
请输入运算符:l
请输入第二个数字:l
Usage:count.sh {+|-|*|/|0-9}

3. for 语句

  用于批量化部署

  格式:for name [ [ in [ word ... ] ] ; ] do list ; done

    for 变量名 in 取值列表; do

    命令

    done
  
  或者

     for 变量名 in 取值列表

      do

      命令

      done

[root@localhost ~]# vim for_test.sh
#!/bin/bash
for i in {1..5}
do
        echo $i
        sleep 1                    #沉睡1秒,即1秒打印一个
done
:wq
[root@localhost ~]# bash for_test.sh
1
2
3
4
5
#实现100以内的偶数/奇数和

[root@localhost ~]#vim count_ou.sh #
!/bin/bash sum=0 for i in `seq 0 2 100` #偶数和 do let sum+=$i done echo $sum :wq [root@localhost ~]# bash count_ou.sh 2550 [root@localhost ~]# vim count_ji.sh #!/bin/bash sum=0 for i in `seq 1 2 100` #奇数和 do let sum+=$i done echo $sum :wq [root@localhost ~]# bash count_ji.sh 2500
#批量检查当前教室192.168.16.(1-10)网段主机是否在线
[root@localhost ~]# vim check_ip.sh
#!/bin/bash
. /etc/init.d/functions                             #引用文件
ip=192.168.16.
for i in {1..10}
do
        if ping -c 1 -w 1 $ip$i &>/dev/null;then    #返回执行结果0或1,其他文件导入黑洞文件
                echo -n "$ip$i"                     #-n,不换行
                success                             #相应function函数
                echo ""                             #输出空格
        else
                echo -n "$ip$i"
                failure
                echo “ ”
        fi
done
[root@localhost ~]# bash check_ip.sh
192.168.16.1                                               [  OK  ]
192.168.16.2                                               [  OK  ]
192.168.16.3                                               [FAILED]
192.168.16.4                                               [FAILED]
192.168.16.5                                               [FAILED]
192.168.16.6                                               [FAILED]
192.168.16.7                                               [FAILED]
192.168.16.8                                               [FAILED]
192.168.16.9                                               [FAILED]
192.168.16.10                                              [FAILED]

4. while语句用于监控

  条件为真就进入死循环;条件为假就退出循环

    格式:while list; do list; done

  while 条件表达式; do

        命令

  done

[root@localhost ~]# vim while_.sh
#!/bin/bash
n=0
while [ $n -lt 5 ]
do
        echo "$n"
        let n++
done
:wq
[root@localhost ~]# bash  while_.sh
0
1
2
3
4

  当条件表达式为 false 时,终止循环。

  条件表达式为 true,将会产生死循环。

  死循环有什么作用那?

  可以用来后台运行检测脚本,如下是是一个检测脑裂的脚本

  我们只需要在命令行中输入 nohup bash naolie.sh & 即可在后台持续运行该脚本

#检测终端数量
[root@localhost ~]# vim check_zh.sh=
#!/bin/bash
while true
do
        num=`who | wc -l`
        echo"当前终端数量为$num"
        sleep 1
done
:wq
[root@localhost ~]# bash check_zh.sh
当前终端数量为5
当前终端数量为5
当前终端数量为6
当前终端数量为6
^C   


#关掉该终端后停止检测 #将检测文件写入文件并放在后台执行 [root@localhost
~]# vim check_zh.sh #!/bin/bash while true do num=`who | wc -l` echo "当前终端数量为$num" >> /root/check_zh sleep 1 done :wq [root@localhost ~]# bash check_zh.sh & #&表示放在后台 [1] 12336 [root@localhost ~]# tail -f check_zh 当前终端数量为3 当前终端数量为3 …..
#关闭写入检测文件的该终端,监测终端停止 #若想关闭终端继续检测,将该监测文件挂起 [root@localhost
~]# nohup bash check_zh.sh & [1] 16949 [root@localhost ~]# nohup: ignoring input and appending output to ‘nohup.out’[root@localhost ~]# ls nohup.out #生成nohup.out文件 在监测则在该终端关闭后无影响 [root@localhost ~]# tail -f check_zh 当前终端数量为3 当前终端数量为3 当前终端数量为2 当前终端数量为2 …….
#若要关掉该监测2关掉运行的进程即可 [root@localhost
~]# ps aux | grep check_zh root 13519 0.0 0.1 113124 1448 ? S 22:19 0:00 bash check_zh.sh root 16949 0.0 0.1 113124 1432 pts/0 S 22:28 0:00 bash check_zh.sh root 18476 0.0 0.0 112648 960 pts/0 R+ 22:31 0:00 grep --color=auto check_zh [root@localhost ~]# kill -9 13519 [root@localhost ~]# kill -9 16949
#逐行读取passwd文件
[root@localhost ~]# vim read.sh
#!/bin/bash
cat /etc/passwd | while read line
do
        echo "$line"
        sleep 1
done
:wq
[root@localhost ~]# bash read.sh
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

5. break和continue语句

  break 是终止循环。

  continue 是跳出当前循环。

[root@localhost ~]# vim test_break.sh
#!/bin/bash
sum=0
while true
do
        if [ $sum -eq 5 ];then
                break
        fi
        let sum++
        echo "$sum"
done
:wq
[root@localhost ~]# bash test_break.sh
1
2
3
4
5
[root@localhost ~]# vim test_continue.sh
#!/bin/bash
sum=0
while true
do
        let sum++
if [ $sum -eq 5 ];then
                continue
        fi
        echo "$sum"
        sleep 1
done
:wq
[root@localhost ~]# bash test_continue.sh
1
2
3
4                                            #跳过了5,仅跳出来此次循环
6
7
8
^C

 

6. case语句(sentos6常用)

  case 语句一般用于选择性来执行对应部分块命令。

  case 模式名    in

  模式 1)

    命令

    ;;

  模式 2)

    命令

    ;;

  *)

     不符合以上模式执行的命令

  esac

  每个模式必须以右括号结束,命令结尾以双分号结束,最后一个模式不需要添加;;。

[root@localhost ~]# vim test_case.sh

#!/bin/bash
case $1 in
[0-9])
        echo "数字"
;;
[a-z])
        echo "a-z"
;;
[A-Z])
        a=`tr $1 a-z`                 #大写转化成小写
        echo "$a"
;;
*)
        echo "结束"
esac
:wq
[root@localhost ~]# bash test_case.sh 1
数字
[root@localhost ~]# bash test_case.sh a
a-z
[root@localhost ~]# bash test_case.sh A
a-z
#内存不足报警

#查看内存
[root@localhost
~]# free total used free shared buff/cache available Mem: 999936 119616 613732 6856 266588 698092 Swap: 0 0 0 [root@localhost ~]# free -h total used free shared buff/cache available Mem: 976M 116M 599M 6.7M 260M 681M Swap: 0B 0B 0B [root@localhost ~]# free -h | grep M Mem: 976M 116M 599M 6.7M 260M 681M [root@localhost ~]# free -h | grep M | cut -d'M' -f4 599 [root@localhost ~]# free -h | grep M | cut -d'M' -f4 | tr -d ' ' 598 [root@localhost ~]# vim mem_warning.sh #!/bin/bash while true do mem=`free -h | grep M | cut -d'M' -f4 | tr -d ' '` if [ $mem -lt 500 ];then echo '当前内存不足,请及时处理' break #警告一次即可 fi done :wq

7. 实训 

1> 写一个脚本: 实现自动化一键部署NFS服务器端和客户端

#服务端:192.168.16.5;客户端:192.168.16.6
.5
[root@localhost ~]# vim nfs_auto_client.sh
#!/bin/bash
mount /dev/cdrom /mnt &>/dev/null
yum install rpcbind nfs-utils -y &>/dev/null
mkdir /zxj &>/dev/null
mount -t nfs 192.168.16.6:/zxj /zxj
df -h
[root@localhost
~]# vim nfs_auto_server.sh #!/bin/bash #desc: This shell is for auto deploy nfs #date: 2019-05-04 #author: zxj #服务端配置 pack_num=`ls /mnt | wc -l` if [ $pack_num -eq 0 ];then mount /dev/cdrom /mnt &>/dev/null #检测是否挂载 fi yum install rpcbind nfs-utils -y &>/dev/null if [ $? -ne 0 ];then exit fi mkdir /zxj &>/dev/null chown -R nsfnabody: /zxj echo "/zxj 192.168.16.6(rw)" > /etc/exports systemctl restart rpcbind nfs &>/dev/null #客户端配置 scp ./nfs_auto_client.sh 192.168.16.5:/root ssh 192.168.16.6 bash /root/nfs_auto_client.sh [root@localhost ~]# bash nfs_auto_server.sh


2> 第二个脚本:实现批量化检测当前教室主机在线状况,在线主机保存至一个文件中
 

[root@localhost ~]# vim check_online.sh
#!/bin/bash
touch online
echo "在线ip:" > online
ip=192.168.16.
for i in {5..20}
do
        if ping -c 1 -w 1 $ip$i &>/dev/null;then
        echo "$ip$i在线"
        echo "$ip$i" >> online
        else
        echo "$ip$i不在线"
        fi
done
cat online
:wq

[root@localhost ~]# bash check_online.sh
192.168.16.5在线
192.168.16.6在线
192.168.16.7不在线
192.168.16.8不在线
192.168.16.9不在线
192.168.16.10不在线
192.168.16.11不在线
192.168.16.12不在线
192.168.16.13不在线
192.168.16.14不在线
192.168.16.15不在线
192.168.16.16在线
192.168.16.17不在线
192.168.16.18不在线
192.168.16.19不在线
192.168.16.20不在线
在线ip:
192.168.16.5
192.168.16.6
192.168.16.16

 
#或者
[root@localhost ~]# vim check_online.sh
#!/bin/bash
touch online
echo "在线ip:" > online
ip=192.168.16.
. /etc/init.d/functions
for i in {5..20}
do
        if ping -c 1 -w 1 $ip$i &>/dev/null;then
        echo -n  "$ip$i"
        success
        echo ""
        echo "$ip$i" >> online
        else
        echo -n "$ip$i"
        failure
        echo ""
        fi
done
cat online
[root@localhost ~]# bash check_online.sh
192.168.16.5                                               [  OK  ]
192.168.16.6                                               [  OK  ]
192.168.16.7                                               [FAILED]
192.168.16.8                                               [FAILED]
192.168.16.9                                               [FAILED]
192.168.16.10                                              [FAILED]
192.168.16.11                                              [FAILED]
192.168.16.12                                              [FAILED]
192.168.16.13                                              [FAILED]
192.168.16.14                                              [FAILED]
192.168.16.15                                              [FAILED]
192.168.16.16                                              [  OK  ]
192.168.16.17                                              [FAILED]
192.168.16.18                                              [FAILED]
192.168.16.19                                              [FAILED]
192.168.16.20                                              [FAILED]
在线ip:
192.168.16.5
192.168.16.6
192.168.16.16

3> 第三个脚本:实现批量化创建100个用户,并创建8位随机密码,且可登陆

#!/bin/bash
for i in {1..100}
do
        useradd user$i
        passwd=`echo $RANDOM | md5sum | cut -c 1-8`
        echo $passwd | passwd --stdin user$i
        echo -e "账户:user$ 
密码:$passwd"
done

4> 第四个脚本:找出系统中含有某个关键词的文件,并输出到终端,关键词用户输入指定

[root@localhost ~]# vim find_key.sh
#!/bin/bash
read -p "Please input your keyword:" key
for file in `find / -type f``
do
        if grep "$key" $file &>/dev/null;then
                echo "$file"
        fi
done
:wq
[root@localhost ~]# bash find_key.sh
Please input your keyword:anaconda  
/boot/grub2/device.map
……

5> 第五个脚本:批量判断当前目录下所有文件类型 

[root@localhost ~]# vim type.sh
#!/bin/bash
for file in `ls /root`
do
        type=`ls -ld $file | cut -c 1`
        if [ "$type" == "-" ];then
                echo "$type------->$file=====普通文件"
        elif [ "$type" == "d" ];then
                echo "$type------->$file=====目录文件" 
        elif [ "$type" == "l" ];then
                echo "$type------->$file=====链接文件"
        else
                echo "$type------->$file=====未知文件"
        fi
done
:wq
[root@localhost ~]# bash type.sh
-------->anaconda-ks.cfg=====普通文件
-------->find_key.sh=====普通文件
-------->type.sh=====普通文件

6> 找到以.sh结尾的文件,计算文件大小总和,以KB为单位 

#方法一: 用cut分割
[root@localhost ~]# vim sum_sh.sh
#!/bin/bash
sum=0
for file in `find / -name "*.sh"`
do
        size=`ls -l $file | cut -d " " -f 5`
        let sum+=$size
done
echo "$(($sum/1024))KB"
[root@localhost ~]# bash sum_sh.sh
623KB

# 方法二:用awk分割
[root@localhost ~]# vim sum_sh1.sh
#!/bin/bash
sum=0
for file in `find / -name "*.sh"`
do
        size=`ls -l $file | awk -F " +" '{printf $5}'`
        let sum+=$size
done
echo "$(($sum/1024))KB"
:wq
[root@localhost ~]# bash sum_sh1.sh
623KB
原文地址:https://www.cnblogs.com/ajunyu/p/10887003.html