Shell 中利用FIFO实现多进程tar解压的方法

上文Shell中使用tar命令批量解压缩的实现方法中提到我使用循环的方法批量解压tar文件,可是单进程的解压耗时太长,须要优化,故决定采用FIFO(有名管道)实现可控并发数的多进程解压。linux

须要直接知道解决方案的请看第二节

1.FIFO(有名管道)简述

FIFO,又称做命名管道(named pipe),它是Linux中用于进程间通讯的一种方法。 FIFO是一种特殊的文件。因为linux全部的事物均可以被视为文件,因此对命名管道的使用也就变得与文件操做很是统一。 FIFO简单理解,就是它能把两个不相关的进程联系起来,FIFO就像一个公共通道,解决了不一样进程之间的“代沟”。普通的无名管道只能让相关的进程进行沟通(好比父shell和子shell之间)。shell

下面模拟了一个FIFO通讯的过程,主要有两个进程:

#!/bin/bash
#Client.sh
#不断向fifo写入数据

tmp_fifo="/tmp/test.fifo"
rm -f $tmp_fifo
mkfifo $tmp_fifo
exec 6<>$tmp_fifo #这句话能把管道变成非阻塞!

i=0
while :
do
	sleep 1                 # 1秒写一次
	echo "$i" >&6
        echo "$i"    
        #输出到终端的时候要当心,会覆盖你的终端,因此要中止,最好直接挂起进程!!
	let i++
done 

exec 6>&-
复制代码
#!/bin/bash
#Server.sh
#不断从fifo中读出数据

tmp_fifo="/tmp/test.fifo"
echo "$tmp_fifo"
exec 6<>$tmp_fifo                 #创建一个绑定

while :
do
        read TEXT
	sleep 1
	echo "$TEXT"          #每1s就读取一个数据,而且打印到终端,要中止,最好挂起进程!
done <&6

复制代码

打开终端A:$ ./Client.shbash

打开终端B:$./Server.sh并发

你就能看到在终端B中从fifo中读取到的数据,你要是在终端B中把每次读fifo的间隔给改为2秒,就更能说明问题了。上面的程序,在实验的时候最好经过不断挂起A进程来查看,而后观察B进程的输出。你会知道FIFO整个是怎么跑的。。。post

FIFO的出现,极好地解决了系统在应用过程当中产生的大量的中间临时文件的问题。FIFO能够被shell调用使数据从一个进程到另外一个进程,系统没必要为该中间通道去烦恼清理没必要要的垃圾,或者去释放该通道的资源,它能够被留作后来的进程使用。而且规避了匿名管道在做用域的限制,可应用于不相关的进程之间。测试

此节参考文章:blog.csdn.net/firefoxbug/…优化

2.利用FIFO实现多进程tar解压

#获取类型(Http等),目录地址,临时方案
type=$1
dir=$2
#获取时间,包括月、日、小时帐期
#测试使用-调度内采用Oracle导入时间参数 
v_month=`date -d "-1 month" '+%Y%m'` #当月
echo $v_month
v_day=`date '+%Y%m%d'` #当日
echo $v_day
#v_hour=`date -d "-1 hour" '+%Y%m%d%H'` #前一个小时
echo $v_hour

#建立临时文件夹
temp='temp_'${type}'_'${v_hour}
echo ${temp}
mkdir ${dir}/${temp}

#声明并发线程并发个数
THREAD=4
#声明管道名称,'$$'表示脚本当前运行的进程PID 
TMPFIFO=/tmp/$$.fifo
 #建立管道
mkfifo $TMPFIFO
#建立文件标示符“5”
#这个数字能够为除“0”、“1”、“2”以外的全部未声明过的字符,以读写模式操做管道文件
#系统调用exec是以新的进程去代替原来的进程,但进程的PID保持不变
#换句话说就是在调用进程内部执行一个可执行文件 
exec 5<>${TMPFIFO}
#清除建立的管道文件 
rm -rf ${TMPFIFO}      

#为并发线程建立一样个数的占位
for((i=1;i<=$THREAD;i++))
do
   echo ;  
 #借用read命令一次读取一行的特性
 #使用一个echo默认输出一个换行符,来确保每一行只有一个线程占位
done >&5        #将占位信息写入管道 

#解压数据 匹配对应类型type和时间戳
for i in `ls ${dir}/*${v_hour}*${type}*`
do 
  #从文件描述符管道中,获取一个管道的线程占位而后开始执行操做;
#read中 -u 后面跟fd,表示从文件描述符中读入,该文件描述符能够是exec新开启的。
  read -u 5
  {
    tar -xzvf $i -C ${dir}/${temp}  #执行压缩 
#任务执行完后在fd5中写入一个占位符,以保证这个线程执行完后,线程继续保持占位
#继而维持管道中永远是固定线程数,&表示该部分命令/任务放入后台不占当前的bash,实现并行处理
    echo "" >&5 
  }&
done 

#等待前面的线程执行
wait  

exec 5>&-  #关闭fd5的管道
复制代码

此节参考文章:blog.csdn.net/qq_34409701…ui

相关文章
相关标签/搜索