shell脚本线程并发控制 #yyds干货盘点#

Posted 江晓龙的技术博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shell脚本线程并发控制 #yyds干货盘点#相关的知识,希望对你有一定的参考价值。

shell并发控制

1.文件描述符

File Descriptors (FD,文件描述符或文件句柄):进程使用文件描述符来管理打开的文件

查看当前进程的fd

确定以下三点

如何exec打开一个文件

​ exec 3<> file1.txt

如何exec关闭一个文件(释放文件句柄)

如果没有释放句柄,文件删除后描述符依然还在

​ exec 3<&-

当一个文件FD未被释放,删除源文件也不会影响FD

​ rm -rf file1

​ cp /proc/$$/3 file1

[root@localhost my_scripts]# ll /proc/$$/fd
总用量 0
lrwx------ 1 root root 64 2月  11 11:35 0 -> /dev/pts/2
lrwx------ 1 root root 64 2月  11 11:35 1 -> /dev/pts/2
lrwx------ 1 root root 64 2月  11 11:35 2 -> /dev/pts/2
lrwx------ 1 root root 64 2月  11 14:07 255 -> /dev/pts/2

创建一个文件
touch /root/file1.txt
exec 3<> /root/file1.txt        在当前进程打开这个文件,3代表文件描述符    

将文件中输入内容
echo "123" >/proc/$$/fd/3
cat /root/file1.txt     这是123就会出现在file1中,因为描述符3打开了这个文件

删除/root/file1
rm -rf /root/file
这时ll /proc/$$/fd就会输出如下结果
[root@localhost my_scripts]# ll /proc/$$/fd
总用量 0
lrwx------ 1 root root 64 2月  11 11:35 0 -> /dev/pts/2
lrwx------ 1 root root 64 2月  11 11:35 1 -> /dev/pts/2
lrwx------ 1 root root 64 2月  11 11:35 2 -> /dev/pts/2
lrwx------ 1 root root 64 2月  11 14:07 255 -> /dev/pts/2
lrwx------ 1 root root 64 2月  11 11:35 3 -> /root/file1.txt (deleted)
表示这个文件已经被删除了

根据描述符恢复删除的文件
cp /proc/$$/fd/3 /root/file1        文件恢复

但是ll /proc/$$/fd/还是会提示3已经删除,这是由于每个文件都一个特定的iload编号

关闭当前进程的文件描述符
exec 3<&-

2.再谈管道

管道分为匿名管道和命名管道

我们平时用的|叫匿名管道,其实匿名管道也是一个文件,只不过他是在我们心目中的,而命名管道是名副其实的文件,由mkfifo命令创建一个命名管道文件,命名管道文件可以跨终端输入,只显示一次。

管道文件不会被覆盖,只有当有人读到这个文件才会消失

终端1
[root@localhost my_scripts]# mkfifo /tmp/fifo1
终端2
[root@localhost ~]# grep sda /tmp/fifo1 等待输入
终端1
[root@localhost my_scripts]# ll /dev/ > /tmp/fifo1
终端2
brw-rw----  1 root disk      8,   0 2月  10 21:36 sda
brw-rw----  1 root disk      8,   1 2月  10 21:36 sda1
brw-rw----  1 root disk      8,   2 2月  10 21:36 sda2    获得内容

再次查看则内容小时,若想再看则重新定向到文件

3.并发控制实例

脚本实现多线程并发控制的原理:

​ 首先定义并发的数量,然后创建管道文件,并往管道文件中插入数据(可以是空行),然后定义分隔符,以分隔符xx运行管道文件,在删除管道文件,因为删除管道文件不会影响句柄,在使用read -u命令读取分隔符内容,如果能读到数据则执行对应的后台进程,如果读取不到则一直等待,并发进程并不是等所有都执行完一轮后在执行新的一轮,而是完成一个后就会返回,比如控制 的并发数是50,那么始终都会是50个后台进程一起执行,直到程序结束

3.1.ping主机实现并发控制

#!/bin/bash
#----------------------控制进程并发数量---------------------
#-------------shell多进程/多线程------------------
#定义控制并发的数量
bfsl=10

#定义管道文件
fifofile=/tmp/$$.fifo

#创建管道文件
mkfifo $fifofile

#以文件描述符3打开管道文件
exec 3<> $fifofile

#删除管道文件,因为文件描述符打开的文件即使删除句柄也不会被释放
rm -rf $fifofile

#循环往管道文件中写入内容
for i in $(seq $bfsl)
do
        echo >&3        #这个表示只写入回车
done

for i in 1..254
do
        read -u 3       #-u表示对文件描述符进行读取,如果能读取则执行下面的命令,如果不能则等待
        
        ip=192.168.81.$i
        ping -c1 -W1 $ip &>/dev/null
        if [ $? -eq 0 ];then
                echo "$ip is up"
        else
                echo "$ip is down"
        fi
        echo >&3        #由于之前是从管道文件中读走了一行,这里要在还回去一行,让后面的进程进行使用
        &
done
wait
exec 3>&-               #释放文件描述符
echo "finish.............."

3.2.创建用户实现并发控制

#!/bin/bash
#------------创建用户实现并发控制------------
#------------shell多线程/多进程-------------------
#并发数量,一次性能同时存在多少个进程
bfcs=50

#管道文件
fifofile=/tmp/user_$$.fifo

#创建管道文件
mkfifo $fifofile

#打开管道文件并定义为分隔符4
exec 4<> $fifofile

#删除管道文件
rm -rf $fifofile

#向管道文件插入空行
for i in $(seq $bfcs)
do
        echo >&4
done

for i in $(seq -w 1000)
do
        read -u 4       #读取分隔符4,如果读到行则执行下面命令,否则一直等待
        
        user=qwe$i
        useradd $user
        echo "123" |passwd --stdin $user &>/dev/null
        if [ $? -eq 0 ];then
                echo "$user is created..."
        fi
        echo >&4        #当运行完命令后则重新向管道文件插入新的行,以便后续进程进行使用
        &
done
wait
exec 4>&-               #当所有循环完成后释放分隔符
echo "finish........."

以上是关于shell脚本线程并发控制 #yyds干货盘点#的主要内容,如果未能解决你的问题,请参考以下文章

#yyds干货盘点# 来,听我讲讲常用并发容器

#yyds干货盘点#shell脚本编程进阶之数组

#yyds干货盘点#linux shell 脚本,将变量拼接到命令中。

#yyds干货盘点# shell脚本入门持续更新一天一个知识点

#yyds干货盘点#JS是单线程的,那么JS是如何实现并发请求的?

Linux 命令行与 shell 脚本编程大全 1.初识Linux shell#yyds干货盘点#