shell脚本中的多线程

        很多场景中会用到多线程,例如备份数据库,有100个库,正常备份效率极其低下。有了多线程原本可能需要10个小时备份,现在分10个线程同时去干,只要一个小时就解决了。今天就介绍下shell中如何使用多线程去完成一些操作,提高我们的效率。

首先我们需要了解以下一些知识点:

1、文件描述符

[root@localhost ~]# touch file1         #先创建一个文件

[root@localhost ~]# exec 6<> file1   #通过exec的方式向当前进程号中丢入一个文件描述符6,关联文件为file1

[root@localhost ~]# ll /proc/$$/fd    #查看当前进程号的文件描述符

total 0

lrwx------ 1 root root 64 Jun 19 13:38 0 -> /dev/pts/0

lrwx------ 1 root root 64 Jun 19 13:38 1 -> /dev/pts/0

lrwx------ 1 root root 64 Jun 19 13:38 2 -> /dev/pts/0

lrwx------ 1 root root 64 Jun 19 13:39 255 -> /dev/pts/0

lrwx------ 1 root root 64 Jun 19 13:38 6 -> /root/file1    #我们丢进来的文件描述符,关联着file1文件

[root@localhost ~]# echo "this is test file" >/proc/$$/fd/6       #向当前进程号的文件描述符6中写入一段内容

[root@localhost ~]# cat file1     #查看file1文件,发现与我们刚写入文件描述符中的内容一致

this is test file

===================================================================================


[root@localhost ~]# rm -rf file1   #删除文件file1

[root@localhost ~]# ll /proc/$$/fd/6    #查看当前进程号中文件描述符6的状态,不难看出对应file1文件的状态问deleted

lrwx------ 1 root root 64 Jun 19 13:38 /proc/14530/fd/6 -> /root/file1 (deleted)

[root@localhost ~]# cp  /proc/$$/fd/6 file1   #拷贝文件描述符6为file1

[root@localhost ~]# cat file1   #查看file1文件,内容与删除一样,未变。有一点,这个复原的file1文件不再是原来的了,因为文件描述符状态依旧为deleted

this is test file

[root@localhost ~]# exec 6<&-      #释放文件描述符

==================================================================================


2、命名管道


[root@localhost ~]# ls *.txt | grep test  #  | 为我们的匿名管道

test2.txt

test.txt

[root@localhost ~]# mkfifo file-fifo   #创建一个命名管道文件file-fifo

[root@localhost ~]# file file-fifo        #查看文件类型为name pipe,命令管道文件,它的特点是1、即拿即用,用完就消失 2、先进先出

file-fifo: fifo (named pipe)

==============================================================================


#起两个终端测试一下

#终端一

[root@localhost ~]# grep "vd" file-fifo 

#终端二

[root@localhost ~]# ls /dev/ > file-fifo

操作完终端二后你会发现终端一马上就会有结果显示,但是你再次grep "vd"的时候则没有任何结果,这就是命名管道文件的特点,即拿即用,用完消失。

==================================================================================


看完上面两个知识点,就进入到我们脚本的正题,如何实现多线程。

脚本如下:

#!/bin/bash
##################
#多线程批量创建用户
#dingxiang
##################
#定义20个线程,以及fifo文件名称
thread=20
file=$(pwd)/file_thread
#创建fifo文件,丢个文件描述符6进去,把fifo文件删掉
mkfifo $file
exec 6<> $file
rm -rf $file

#向文件描述符6中写入20个空行
for i in `seq $thread`
do
        echo >&6
done

#创建alice1-alice500个用户
for j in `seq 500`
do
#read -u 读文件描述符6
        read -u 6
#创建用户,因为每次拿20个空行,所以创建完之后再还20个空行回去
        {
        useradd alice$j
        echo "123123" | passwd --stdin alice$j  &>/dev/null
        echo "alice$j creat....."
        echo >&6
        }&
done
#等待上面所有的操作结束
wait
#释放文件描述符,echo;all is ok
exec 6>&-
echo "all is ok......."

执行脚本会发现,用户创建成功给予的提示是一组一组刷出来的,而不是之前一个个的创建,一个个的提示。

事实上这样并不是真正意义上的多线程,只是伪多线程,但在实际场景中真的很好用。