iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 22
0
自我挑戰組

30 天的 ShellScript 教室解決開發者的困擾系列 第 23

[鐵人賽原訂第23天] Shell 的多執行緒

打掃房間打掃到超過 12 點,這實在是太沮喪啦。

不過這陣子台中的 PM 2.5 真恐怖,白色的抱枕整個變成灰的,看來賽車女郎 Saber 要晚點才能買惹QQ

前天寫到我們用 for 迴圈砍了數百個分支,雖然指令下完可以丟著等,但是總覺得沒啥效率。事實上 Shell 是可以允把指令丟到背景跑的,然後前景繼續做其他事情。

作法如下:

  1. 準備一個普通的指令
  2. 後面加上一個 & 號,完工。

對,就這樣而已,stdout 跟 stderr 會與前景程式混在一起,所以用起來真的不太好用。至於如何列出目前在背景值型的程式呢?

jobs -l 
[1]    100854 running    sleep 30
[2]    100891 running    sleep 30
[3]  - 100899 running    sleep 30
[4]  + 100907 running    sleep 30

第一行是指令,後面是顯示結果。第一欄是第幾個 job ,後面的 + - 號鳥哥有寫,第三欄是 pid ,第四欄是狀態,第五欄是指令。

當背景程式執行完,會出現下面的訊息(一樣跟前景程式的 stdout / stderr 混在一起):

[1]  + 100644 done       sleep 10

如果要切換回背景執行的程式,可以用 fg 這個指令。如果要指令跳到第三個,就執行 fg %3

以昨天來講,昨天原本的指令是這樣:

for branch in `cat branch.txt`; do
    git push origin :$branch
done

改成這樣就可以變成背景執行了:

for branch in `cat branch.txt`; do
    git push origin :$branch &
done

不過使用這個方法請注意:

  1. 被 github 當 DDoS 可能就要等更久了
  2. 畫面會不斷的跳出 [1] + 100644 done git push origin :use-vue 之類的訊息

請謹慎使用,當然你也可以限制每秒只增加一個背景程序:

for branch in `cat branch.txt`; do
    git push origin :$branch &
    sleep 1
done

不過這有個問題,你沒辦法控制到底有幾個執行緒在背景執行,萬一網路狀況特別差,就換記憶體遭殃啦。不過遇到問題就要解決嘛:

for branch in `cat branch.txt`; do
    git push origin :$branch &
    while [ `jobs -l | tail -n 1 | cut -d ' ' -f 1 | sed 's/\[//g' | sed s/\]//g` -ge 10 ]; do
        sleep 1
    done
done

tail 的功能是取檔案最後數行資料,可以用 -n 控制;[ 可以 -ge 表示 >= ,詳細請 man [。這個指令之前沒講的地方就這些了。

這樣,就可以確保不會有超過 10 個背景程式再跑啦,不過這麼長一串有違偷懶原則,看看就好


上一篇
[鐵人賽第22天] 實戰:清理 git repo 遠端分支
系列文
30 天的 ShellScript 教室解決開發者的困擾23
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言