shell之循环及并发数控制

文章目录

    • 循环及并发数控制
      • 语法结构
      • `for`循环并发删除用户
      • for在读取行获取参数时以空格为分隔符,while可将行作为分隔符
      • 并发控制(FD和命名管道实现并发)
        • - FD文件句柄
        • - 命名管道
        • - 案例:FD和命名管道实现并发数控制

循环及并发数控制

for while until循环

语法结构

1. =======for循环======================
for 条件测试
do
    循环体
done
=======当条件为真时,执行循环体=======

2. =======while循环===================
while 条件测试
do
    循环体
done
========当条件为真时,执行循环体=======

3. =======until循环====================
until 条件测试
do
    循环体
done
========当条件为假时,执行循环体=======

for循环并发删除用户

#!/usr/bin/bash
. /etc/init.d/functions

Prefix=lss

for i in `seq 10`
do
        {
                User=$Prefix$i
                id $User &> /dev/null
                if [ $? -eq 0 ];then
                        userdel -r $User && action "userdel $User" /bin/true
                else
                        echo ""
                        action "NO $User" /bin/false
                fi
        }&              #中间这段直接放到后台执行

done
wait                    #等前面放到后台的所有任务都执行完毕,在执行后面的
echo "END"

//测试删除lss1~lss10
[root@mysql-master /soft/scripts]# ./userdel.sh 

NO lss10                                                  [FAILED]
userdel lss6                                               [  OK  ]
userdel lss7                                               [  OK  ]
userdel lss3                                               [  OK  ]
userdel lss4                                               [  OK  ]
userdel lss8                                               [  OK  ]
userdel lss9                                               [  OK  ]
userdel lss1                                               [  OK  ]
userdel lss5                                               [  OK  ]
userdel lss2                                               [  OK  ]
END
[root@mysql-master /soft/scripts]#

for在读取行获取参数时以空格为分隔符,while可将行作为分隔符

// for在读取行获取参数时以空格为分隔符
例如:文件user.txt
[root@mysql-master /soft/scripts]# cat user1.txt
lss1 123
lss2 1233

lss3    2345

#!/usr/bin/bash
#希望for处理文件按回车分隔,而不是空格或tab
#用IFS重新定义分隔符
#IFS内部字段分隔符
echo "用IFS处理前"
for line in `cat user1.txt`
do
        user=`echo $line|awk '{print $1}'`
        pass=`echo $line|awk '{print $2}'`
        echo "User:$user Passwd:$pass"
done
echo "用IFS处理后"
IFS=$'\n'
for line in `cat user1.txt`
do
        user=`echo $line|awk '{print $1}'`
        pass=`echo $line|awk '{print $2}'`
        echo "User:$user Passwd:$pass"
done
[root@mysql-master /soft/scripts]# ./fortest.sh 
用IFS处理前
User:lss1 Passwd:
User:123 Passwd:
User:lss2 Passwd:
User:1233 Passwd:
User:lss3 Passwd:
User:2345 Passwd:
用IFS处理后
User:lss1 Passwd:123
User:lss2 Passwd:1233
User:lss3 Passwd:2345
[root@mysql-master /soft/scripts]# 

  • while比较适合处理文件,可直接获取到行
[root@mysql-master /soft/scripts]# vim batch_useradd4.sh 
#!/usr/bin/bash

while read line
do
        User=`echo $line|awk '{print $1}'`
        Password=`echo $line|awk '{print $2}'`
        id $User &>/dev/null
        if [ $? -eq 0 ];then
                echo "$User is already exists or Format error"
        else
                useradd $User && echo "$Password" |passwd --stdin $User &>/dev/null
                if [ $? -eq 0 ];then
                        echo "$User is created"
                fi
        fi
done < /soft/scripts/user1.txt

//测试
[root@mysql-master /soft/scripts]# sh batch_useradd4.sh 
lss1 is created
lss2 is created
 is already exists or Format error
lss3 is created
[root@mysql-master /soft/scripts]# 

并发控制(FD和命名管道实现并发)

- FD文件句柄


//通过exec 3<> ip2.txt 打开文件
//通过exec 3<&- 关闭文件(释放文件句柄)
//文件删除不要紧,只要文件没被关闭句柄还在,就依然可以将文件还原cp /proc/$$/fd/6 ip2.txt

//fd 文件句柄没有被释放,还可以cp回来
[root@mysql-master /soft/scripts]# exec 6<> ip2.txt    #打开文件
[root@mysql-master /soft/scripts]# cat ip2.txt 
192.168.1.4
...
[root@mysql-master /soft/scripts]# ll /proc/$$/fd
...
lrwx------ 1 root root 64 Oct 28 03:36 6 -> /soft/scripts/ip2.txt
[root@mysql-master /soft/scripts]# rm -f ip2.txt 
[root@mysql-master /soft/scripts]# ll /proc/$$/fd
...
lrwx------ 1 root root 64 Oct 28 03:36 6 -> /soft/scripts/ip2.txt (deleted)

//通过文件句柄恢复文件
[root@mysql-master /soft/scripts]# ll /proc/$$/fd
...
lrwx------ 1 root root 64 Oct 28 03:36 6 -> /soft/scripts/ip2.txt (deleted)
[root@mysql-master /soft/scripts]# cp /proc/$$/fd/6 /soft/scripts/ip2.txt
[root@mysql-master /soft/scripts]# cat ip2.txt 
192.168.1.4
...

//关闭文件句柄
[root@mysql-master /soft/scripts]# exec 6<&-    #关闭文件
[root@mysql-master /soft/scripts]# ll /proc/$$/fd       #文件句柄被释放
total 0
lrwx------ 1 root root 64 Oct 28 03:36 0 -> /dev/pts/1
lrwx------ 1 root root 64 Oct 28 03:36 1 -> /dev/pts/1
lrwx------ 1 root root 64 Oct 28 03:36 2 -> /dev/pts/1
lrwx------ 1 root root 64 Oct 28 05:13 255 -> /dev/pts/1
[root@mysql-master /soft/scripts]# 

- 命名管道

//创建命名管道
[root@mysql-master /soft/scripts]# mkfifo /tmp/tmpfifio

//测试
//先在1终端准备接受管道放入的命令
[root@mysql-master /soft/scripts]# tty
/dev/pts/1
[root@mysql-master /soft/scripts]# grep yum /tmp/tmpfifio
//然后在0终端放入rpm -qa命令到/tmp/tmpfifio管道中
[root@mysql-master /soft/scripts]# 
[root@mysql-master /soft/scripts]# tty
/dev/pts/0
[root@mysql-master /soft/scripts]# rpm -qa > /tmp/tmpfifio   #回车后1终端局可以拿到命令,最后管道变成空了

// /dev/pts/1
[root@mysql-master /soft/scripts]# grep yum /tmp/tmpfifio 
yum-plugin-fastestmirror-1.1.31-45.el7.noarch
yum-metadata-parser-1.1.4-10.el7.x86_64
yum-3.4.3-158.el7.centos.noarch
[root@mysql-master /soft/scripts]# 


- 案例:FD和命名管道实现并发数控制

[root@mysql-master /soft/scripts]# vim thread_ping.sh
#最大并发数
Thread_num=5
#命名管道文件
Tmp_fifo=/tmp/$$.fifo

#创建命名管道文件
mkfifo $Tmp_fifo
#用文件句柄(随便给个6)打开管道文件
exec 6<> $Tmp_fifo
rm -f $Tmp_fifo

##控制并发数
for i in `seq $Thread_num`
do
        #向管道中放入最大并发数个行,供下面read读取
        echo >&6
done

##
IP=192.168.1

for i in {1..254}
do
        #通过文件句柄读取行,当行取尽时,停止下一步(并发)
        read -u 6
        {
                ping -c1 -W1 $IP.$i &>/dev/null
                if [ $? -eq 0 ];then
                        echo "$IP.$i is UP"
                else
                        echo "$IP.$i is DOWN"
                fi
        #一个并发执行后要想管道中在加入一个空行,供下次使用
        echo >&6
        }&
done
wait
echo "END"

你可能感兴趣的:(Shell)