1. 程式人生 > >Linux-Shell-使用mkfifo實現多工併發及併發數控制

Linux-Shell-使用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 [email protected]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 [email protected]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 [email protected]126.com

這裡添加了“wait” 之後就可以達到我們預期的效果了,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

相關推薦

Linux-Shell-使用mkfifo實現併發併發控制

預設的情況下,Shell指令碼中的命令是序列執行的,必須等到前一條命令執行完後才執行接下來的命令,但是如果我有一大批的的命令需要執行,而且互相又沒有影響的情況下(有影響的話就比較複雜了),那麼就要使用命令的併發執行了。 如下: #!/bin/bash

Linux系統程式設計——執行緒實現

概述 每個程序都擁有自己的資料段、程式碼段和堆疊段,這就造成程序在進行建立、切換、撤銷操作時,需要較大的系統開銷。為了減少系統開銷,從程序中演化出了執行緒。為了讓程序完成一定的工作,程序必須至少包含一個執行緒。執行緒存在於程序中,共享程序的資源。更多詳情,請看《程序和執行緒的區別與聯絡》

系統API函實現線程線程同步

容易 erro include man pre art Owner 參數 全局 1、線程的創建   須包含頭文件:#include <windows.h>   HANDLE CreateThread(     LPSECURITY_ATTRIBUTES lp

linux--shell編程(三)條件判斷算術運算

寫一個腳本 head bsp 如何 cut inittab 引用 有用 color 練習:寫一個腳本判斷當前系統上是否有用戶的默認shell為bash; 如果有,就顯示有多少個這類用戶;否則,就顯示沒有這類用戶; #!/bin/bash # grep ‘\<ba

Linux 使用grep篩選個條件grep常用過濾命令

cat log.txt | grep 條件;  cat log.txt | grep 條件一 | grep 條件二;  cat log.txt | grep 條件一 | grep 條件二 | grep 條件三; grep 條件一 log.txt | grep 條件二 | gr

Linux環境下實現臺kvm虛擬機器之間組成amp架構連線

規劃圖 一、安裝kvm 1、環境準備 安裝之前,需要lscpu看flag是否包含svm或者vmx,該標誌表示cpu是否支援硬體虛擬化,而且需要64位架構,命令:lscpu | egrep 'vmx|lv|svm' 如果用的是vmware,需要開啟 開機後再檢視,模組已經裝入(Cent

springBoot+scheduling實現動態定時任務

 使用spring自帶的scheduling定時排程任務相當於輕量級的Quartz,但是不支援分散式,若要實現分散式定時任務就得使用Quartz了. 第一步,在入口類中宣告定時任務 import org.springframework.boot.SpringApplicatio

Java基礎之執行緒併發

實際上關於多執行緒的基礎知識,前面自己已經總結過一部分,但是每一個階段對於同樣知識點的學習側重點是不一樣的,前面的Java基礎總結八之多執行緒(一)和 Java基礎總結九之多執行緒(二)是對JDK5以前多執行緒相關基礎知識的一個簡單總結,今天本文將偏重於JDK5提供的併發庫進行學習總結。 首先,

python3.5進階(三)-------------實現之協程(生成器,迭代器)

1.迭代器:迭代是訪問集合元素的一種方式,迭代器是可以記住遍歷的位置的物件,迭代器物件從集合的第一個元素開始訪問,直到所有訪問結束,迭代器只能前進不能後退。判斷一個數據型別是否可以迭代,看是否能for迴圈。如(字串,列表,元祖...)序列可以迭代,數字不能迭代,或通過isintance([11,12

python3.5進階(三)-------------實現之程序

1. 程式:硬碟上的exe,是靜態的(一段程式碼程式碼)。通俗的說,程式在硬碟上執行起來(如雙擊qq.exe)就是程序,一般一個程式,可以有多個程序,如一個QQ程式,可以同時開啟登入多個QQ號程序。   2. 程序與執行緒的區別:都能實現多工。程式執行時,先將靜態程式碼

Shell指令碼併發併發控制

https://www.jianshu.com/p/701952ffb755 正常情況下,Shell指令碼是序列執行的,一條命令執行完才會執行接下來的命令。如下程式碼: !/bin/bash for i in seq 1 10 do echo $i done echo “----

如何使用ajax實現條刪除前後端互動

/*多條刪除,以下程式碼是本人在springCloud中寫的, 但是方法都大同小異,你看懂了,也就會了*/ JSP頁面如下: <%@ page language='java' pageEncoding='UTF-8'%> <%@tagli

Linux中LAMP實現、SQL語句FTP與Samba服務配置

1、 搭建php-fpm工作方式的LAMP環境,實現wordpress正常訪問 Mysql服務的搭建 [[email protected] ~]# yum -y install mariadb-server.x86_64 [[email protected] ~]# ca

Python 協程,gevent(yield阻塞,greenlet),協程實現(有規律的交替協作執行)

實現多工:程序消耗的資源最大,執行緒消耗的資源次之,協程消耗的資源最少(單執行緒)。 gevent實現協程,gevent是通過阻塞程式碼(例如網路延遲等)來自動切換要執行的任務,所以在進行IO密集型程式時(例如爬蟲),使用gevent可以提高效率(有效利用網路延遲的時間去執行其他任務)。 &

程序(程序實現

1.程序 1.程式:靜態的,一個.py檔案就是儲存在硬碟中的,屬於靜態的概念 2.程序:動態的,程式碼加所需的資源 = 程序,是作業系統分配程式執行資源的單位,多程序也是可以滿足多工的 2.程序的狀態有:

python 程序實現

1.匯入程序模組     import multiprocessing 1.2 Process程序類的語法結構如下: Process([group [, target [, name [, args [, kwargs]]]]]) group:指定程序組,目前只能使用

在PHP中使用協程實現排程

PHP5.5一個比較好的新功能是加入了對迭代生成器和協程的支援.對於生成器,PHP的文件和各種其他的部落格文章已經有了非常詳細的講解.協程相對受到的關注就少了,因為協程雖然有很強大的功能但相對比較複雜, 也比較難被理解,解釋起來也比較困難. 這篇文章將嘗試通過介紹如何使用協程來實施

linux下如何實現個定時器

最近在linux下寫一個庫,是給別人用的,要用到定時器這個功能,而且是多定時器任務的,在windows下實現是很方便的,但是 在linux下就遇到了問題,linux下一個程序只能有一個定時器,如果我用了定時器去實現我的任務,那肯定是沒問題的,如果用我庫的人自己也建立了一個定

jmeter-實現個業務混合併發壓力測試

      測試伺服器過程中,可能遇見這種測試需求:同一時間多個不同事務向伺服器發出請求。例如對一個伺服器來說,同一時刻可能有使用者正在登陸,有使用者正在瀏覽網頁,有使用者正在寫資料,有使用者正在退出等等,那麼該如何實現以上場景的壓力測試呢?       假設測試需求如下:對

執行緒(執行緒實現

多工 多工指在作業系統中可以同時執行多個任務,現在的大多數系統都是多工的 作用:能夠充分合理的運用系統的資源,讓其作用發揮到最大 實現多工有哪些方式呢? 1.多執行緒 2.多程序 3.多協程 今天主要說說多執行緒實現多工 首先了解了解並行與併