一、怎麼理解shell併發:
當咱們在執行一個for循環時,假設這個for循環須要循環500次,每循環一次就須要1秒,當這個for循環的腳本執行完畢時,就須要500秒,這樣看效率有些低(尤爲在量級高的時候,會更明顯),因此咱們須要shell腳本的for循環不管循環多少次,讓它們同時執行,不須要按順序循環,這就是shell腳本的併發。
二、如何實現shell腳本併發:
實現很是簡單,就是在循環體的{}後面加上一個&符號,表明每次循環體的命令都放入後臺運行
三、經典實例:
判斷192.168.80.0/24網絡,當前在線的主機數以及IPshell
#!/bin/bash . /etc/init.d/functions cmd="ping -c 2" for ((i=1;i<=254;i++));do { $cmd 192.168.80.$i &>/dev/null if [ $? = 0 ];then action "192.168.80.$i" /bin/true fi }& #將{}循環體放入後臺執行 done wait #等待上面放入後臺的命令執行完畢後,在往下執行(若是後面還有要執行的命令,最好加上wait),由於命令一旦放到後臺執行,這條任務就交個操做系統了,shell腳本會不等上面的執行完畢,就會繼續往下執行。
擴展知識點:
咱們知道了什麼是shell腳本的併發,試想一下,若是此時有1000個任務併發,就會有1000個線程產生,若是系統的資源跟不上,就會讓計算機系統產生很大的壓力,致使操做系統處理的速度會愈來愈慢。而此時咱們又當如何解決呢?出現這個狀況時,咱們能夠引入命名管道文件來處理。
命名管道處理的思路:
就至關於此時有10個開水房間,配有10把鑰匙,此時有100我的要打開水,那麼前10我的搶到鑰匙,就先進去打開水,後面的90我的就須要等前面一我的出來後還回鑰匙,在拿着鑰匙進去打開水,這樣就能控制100我的打開水的任務,同時不會將系統的資源一次性耗用太多,增長壓力,減少處理速度。
知識點:
一、命名管道的特性
若是管道內容爲空,則阻塞
管道具備讀一個少一個,存一個讀一個的性質,放回去的能夠重複取
能夠實現隊列控制
二、若是管道放一段內容沒有人取,則會阻塞
解決上述問題,能夠經過文件描述符
文件描述符具備管道的全部特性,同時還具備一個管道不具備的特性:無限存不阻塞,無限取不阻塞,無需關注管道內容
建立方式:
一、建立命名管道mkfifo /tmp/fl
二、建立文件描述符100,並關聯到管道文件exec 100<>/tmp/fl
三、調用文件描述符,向管道里存放內容,同時也表示將用完的管道內容在放回管道echo >&100
四、讀取文件描述符關聯管道中的內容
`read -u100``
五、關閉文件描述符的讀和寫bash
exec 100<&- exec 100>&-
實例演示:引用上面的網絡測試案例網絡
#!/bin/bash . /etc/init.d/functions cmd="ping -c 2" mkfifo /tmp/fl exec 100<>/tmp/fl rm -rf /tmp/fl for ((n=1;n<=100;n++));do echo >&100 done for ((i=1;i<=254;i++));do read -u100 { $cmd 192.168.80.$i &>/dev/null if [ $? = 0 ];then echo "192.168.80.$i is ok" else echo "192.168.80.$i is no" fi echo >&100 #將管道內容在放回去 }& done wait #echo "test compelet" exec 100<&- exec 100>&-