並行運行多個資料夾中的腳本

並行運行多個資料夾中的腳本

我在高級目錄中有幾個子目錄。每個子目錄都有幾個檔案和一個for循環shell腳本。每個子目錄中都存在相同的 for 迴圈腳本。我想進入每個子目錄並在多個終端中並行運行 for 循環腳本。我嘗試了這個,但它似乎是串行執行的(一個接一個),但我想並行運行所有這些。

find dir_* -type f -execdir sh for_loop.sh {} \;

答案1

假設這做了正確的事情 - 僅以串行方式:

find dir_* -type f -execdir sh for_loop.sh {} \;

那麼你應該能夠將其替換為:

find dir_* -type f | parallel 'cd {//} && sh for_loop.sh {}'

要在多個終端機中運行它,GNU Parallel 支援在其自己的窗格tmux中運行每個命令:tmux

find dir_* -type f | parallel --tmuxpane 'cd {//} && sh for_loop.sh {}'

預設情況下,每個 CPU 核心執行一項作業。在您的情況下,您可能希望比您擁有的核心多運行一項作業:

 find dir_* -type f | parallel -j+1 --tmuxpane 'cd {//} && sh for_loop.sh {}'

GNU Parallel 是一個通用並行器,可以輕鬆地在同一台電腦或多台您可以透過 ssh 存取的電腦上並行運行作業。

如果您想要在 4 個 CPU 上執行 32 個不同的作業,則並行化的直接方法是在每個 CPU 上執行 8 個作業:

簡單的調度

相反,GNU Parallel 在完成後會產生一個新進程 - 保持 CPU 處於活動狀態,從而節省時間:

GNU 平行調度

安裝

出於安全原因,您應該使用軟體套件管理器安裝 GNU Parallel,但如果 GNU Parallel 未針對您的發行版打包,您可以進行個人安裝,這不需要 root 存取權限。這樣做可以在 10 秒內完成:

$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
   fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 883c667e01eed62f975ad28b6d50e22a
12345678 883c667e 01eed62f 975ad28b 6d50e22a
$ md5sum install.sh | grep cc21b4c943fd03e93ae1ae49e28573c0
cc21b4c9 43fd03e9 3ae1ae49 e28573c0
$ sha512sum install.sh | grep da012ec113b49a54e705f86d51e784ebced224fdf
79945d9d 250b42a4 2067bb00 99da012e c113b49a 54e705f8 6d51e784 ebced224
fdff3f52 ca588d64 e75f6033 61bd543f d631f592 2f87ceb2 ab034149 6df84a35
$ bash install.sh

其他安裝選項,請參閱http://git.savannah.gnu.org/cgit/parallel.git/tree/README

了解更多

查看更多範例:http://www.gnu.org/software/parallel/man.html

觀看介紹影片:https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

瀏覽本教學:http://www.gnu.org/software/parallel/parallel_tutorial.html

註冊電子郵件清單以獲得支援:https://lists.gnu.org/mailman/listinfo/parallel

答案2

也許最完美的工具是GNU 平行

parallel ::: dir_*/for_loop.sh

GNU Parallel 不僅並行運行每個作業,而且還對它們的輸出進行多路分解,這樣它們就不會互相干擾。

從其手冊頁:

GNU並行是一種shell工具,用於使用一台或多台電腦並行執行作業。作業可以是單一命令或必須針對輸入中的每一行運行的小腳本。典型的輸入是檔案清單、主機清單、使用者清單、URL 清單或表格清單。作業也可以是從管道讀取的命令。然後,GNU並行可以將輸入分割成區塊,並將區塊並行地傳送到每個命令中。

如果您今天使用 xargs 和 tee,您會發現 GNU 並行非常易於使用,因為 GNU 並行被編寫為具有與 xargs 相同的選項。如果你在shell中寫循環,你會發現GNU並行可能能夠取代大部分循環,並透過並行運行多個作業使它們運行得更快。

GNU 並行確保指令的輸出與順序運行指令時得到的輸出相同。這使得可以使用 GNU 並行的輸出作為其他程式的輸入。

答案3

find不會為你做那件事。

建立一個腳本,找到 for_loop.sh 腳本並執行它們,如下所示:

#!/bin/bash

for theScript in $(find dir_* -name for_loop.sh); do
  "$theScript" &
done

如果腳本必須在子目錄內運行,請嘗試cd進入之前,也許像cd $(dirname "$theScript") && . $(basename "$theScript").

我的例子沒有經過詳細測試並且不具有容錯性...

編輯1:

作為佐藤桂註解正確,如果目錄名稱中有空格,上面的腳本就會中斷。

所以我改為循環read

#!/bin/bash
find dir_* -name for_loop.sh | while IFS= read -r theScript; do
  "$theScript" &
done

答案4

你可以從你的頂級目錄做

for D in `find . -type d -maxdepth 1`
do 
     $D/<yourScriptName>.sh &
done

「&」是在後台運行它們

相關內容