Linux-Schell-mkfifoによるマルチタスク同時および同時数制御


デフォルトでは、Shellスクリプトのコマンドはシリアルで実行され、前のコマンドが実行されるまで待たなければなりませんが、私が多くのコマンドを実行する必要があり、お互いに影響がない場合(影響があれば複雑です)、コマンドの同時実行を使用します.
次のようになります.
#!/bin/bash
IPLIST=/home/meta/ipinfo/iplist
for i in $(cat ${IPLIST} |grep -viE "^#|  |ts"|awk '{print $1}')
do
    ssh $i "cd ~/update/;tar zxf patch-20160909.tgz -C ~/LMDG/ && echo '/$i ok' || echo '/$i bad'"
done >> result.txt

echo "resutl"|mutt -a result.txt -s update-result meta@126.com

上記のコードでは、iplistにはipがたくさんあるので、「tar zxf」ごとに時間がかかるので、同時プログラミングを使うつもりで、時間を節約できます.
次のように変更します.
#!/bin/bash
IPLIST=/home/meta/ipinfo/iplist
for i in $(cat ${IPLIST} |grep -viE "^#|  |ts"|awk '{print $1}')
do
    ssh $i "cd ~/update/;tar zxf patch-20160909.tgz -C ~/LMDG/ && echo '/$i ok' || echo '/$i bad'" &
done >> result.txt

echo "resutl"|mutt -a result.txt -s update-result meta@126.com

「&」を加えると「tar zxf」が並列に実行されます.実質的に「tar zxf」をバックグラウンドプロセスとして実行することで、このコマンドは現在のbashを占有することなく、他のコマンドも前のコマンドの実行が完了してから続行する必要がなく、複数のタスクをバックグラウンドに入れることができ、マルチタスクの同時実行を実現することができる.
私はもともと「tar zxf」というループをすべて実行した後、「mutt」の前の結果を譲ることを目的としていました.上記のように書くと、「tar zxf」がまだ終わっていないうちに「mutt」が実行され始め、誤った結果が得られるので、以下の修正が必要です.
#!/bin/bash
IPLIST=/home/meta/ipinfo/iplist
for i in $(cat ${IPLIST} |grep -viE "^#|  |ts"|awk '{print $1}')
do
    ssh $i "cd ~/update/;tar zxf patch-20160909.tgz -C ~/LMDG/ && echo '/$i ok' || echo '/$i bad'" &
done >> result.txt
wait
echo "resutl"|mutt -a result.txt -s update-result meta@126.com

ここで「wait」を追加すると、サブタスクが完了した後、親タスクが終了し、次のタスクが実行されるのを待つ役割を果たします.
しかし、このiplistの量が大きい場合、一気にバックグラウンドに置くと、システムが負荷を超えると、性能が悪くなったり、ダウンタイムのリスクがあるため、コンカレント数を制御するメカニズムが必要です.そこで,タスクキューの概念を導入し,以前のsocket例の消費者生産者モデルと少し類似しており,メッセージキューによって需給のアンバランスを調整する修正は以下の通りである.
#!/bin/bash

IPLIST=/home/meta/ipinfo/iplist #  (   )
THREAD=50                       #          ,         ,             
TMPFIFO=/tmp/$$.fifo			#      ,'$$'           PID
mkfifo $TMPFIFO                #    
exec 5<>${TMPFIFO}             #       “5”,        “0”、“1”、“2”            ,           ;    exec              ,    PID    ,                      
rm -rf ${TMPFIFO}              #         

#              
for((i=1;i<=$THREAD;i++))
do
   echo ;               
 #  read           ,    echo         ,              ;          &     ,          ,         ,          ,     ,            。
done >&5                
 #         

for i in $(cat ${IPLIST} |grep -viE "^#|  |ts"|awk '{print $1}') #            
do
        read -u5        
 #         ,                   ;read  -u    fd,           ,         exec    。
        {
               echo $(cat ~/ipinfo/iplist|grep $i|awk '{print $2}');
               ssh -oConnectTimeout=10 -oConnectionAttempts=3 $i "cd /home/Log/;grep 'MIL' mission_2016-08-03*.log |awk -F, '{if(\$19==1370) print \$0}'|
               awk -F, '{if(\$20==0) print \$0}'>miss_info.txt"
               echo "" >&5  
 #       fd5        ,           ,        ,          50    ,&       /           bash,      
        } &
done
wait                #                               
exec 5>&-           #  fd5   
exit 0