複数のフォルダ内のスクリプトを並行して実行する

複数のフォルダ内のスクリプトを並行して実行する

上位ディレクトリ内に複数のサブディレクトリがあります。各サブディレクトリには、複数のファイルと for ループ シェル スクリプトがあります。各サブディレクトリには同じ 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 コアごとに 1 つのジョブになります。コア数よりも 1 つ多いジョブを実行したい場合があります。

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

GNU Parallel は汎用的な並列化ツールであり、同じマシン上または SSH アクセスできる複数のマシン上でジョブを並列に実行することを容易にします。

4 つの CPU で実行したい 32 個の異なるジョブがある場合、並列化するための最も簡単な方法は、各 CPU で 8 つのジョブを実行することです。

シンプルなスケジュール

GNU Parallel は、代わりに、1 つのプロセスが終了すると新しいプロセスを生成します。これにより、CPU がアクティブな状態になり、時間が節約されます。

GNU 並列スケジューリング

インストール

セキュリティ上の理由から、GNU Parallel はパッケージ マネージャーを使用してインストールする必要がありますが、GNU Parallel がディストリビューションにパッケージ化されていない場合は、ルート アクセスを必要としない個人用インストールを行うことができます。次の操作を実行すると、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 は各ジョブを並列に実行するだけでなく、ジョブの出力を多重分離して、ジョブが互いに干渉しないようにします。

man ページから引用:

GNU parallel は、1 台以上のコンピュータを使用してジョブを並列に実行するためのシェル ツールです。ジョブは、入力の各行に対して実行する必要がある単一のコマンドまたは小さなスクリプトです。一般的な入力は、ファイルのリスト、ホストのリスト、ユーザーのリスト、URL のリスト、またはテーブルのリストです。ジョブは、パイプから読み取るコマンドである場合もあります。GNU parallel は、入力をブロックに分割し、各コマンドにブロックを並列にパイプします。

現在 xargs と tee を使用している場合、GNU parallel は xargs と同じオプションを持つように記述されているため、非常に使いやすいことがわかります。シェルでループを記述する場合、GNU parallel はループのほとんどを置き換えることができ、複数のジョブを並列に実行することでループの実行速度を上げることができることがわかります。

GNU parallel は、コマンドの出力が、コマンドを順番に実行した場合と同じ出力になるようにします。これにより、GNU parallel の出力を他のプログラムの入力として使用できるようになります。

答え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

「&」はバックグラウンドで実行します

関連情報