フォルダー内のBashスクリプトをすべて同時に実行する


10

.shフォルダ(my_folder)に5つのBash()スクリプトがあり、次のように名前が付けられているとします。

script_1.sh
script_2.sh
script_3.sh
script_4.sh
script_5.sh

6番目のBashスクリプトまたはこれらすべてのスクリプトを一緒に実行し始める1つのライナーだけを作成するにはどうすればよいですか?

同時に実行するのではなく、順番に5つのスクリプトを実行する必要があります。


回答:


12

GNU parallelはこの種のものに最適です。インストールしsudo apt install parallelてから:

parallel -j0 ::: my_folder/*sh

-jtは並行して実行どのように多くのプロセスコントロール、および-j0手段「それらのすべて」。-j20代わりに別の値(たとえば)に設定して、スクリプトをバッチで実行します。


1
注:パッケージparallelからのコマンドもありmoreutilsます。使用例:parallel -j 20 -- my_folder/*.sh(GNU parallel-j0は異なり、スクリプトは一度に1つずつ実行されます)。
jfs

1
@jfs良い点。ただしsudo apt install parallel、このファイルは/usr/bin/parallelGNU Parallelのファイルに置き換えられます。したがって、インストールすると、私の答えが示唆するように、期待どおりに機能するはずです。
terdon

はい、parallelGNUパラレルを提案するための私の答えを書いている間に、マニュアルからコマンドを失敗させようとしたとき、私はそれが難しい方法だとわかりました。
jfs

9

すべてのスクリプトを同時に(並行して)実行するには、次のコマンドを使用します。

script_1.sh &
script_2.sh &
script_3.sh &
script_4.sh &
script_5.sh &

次々と(順番に)実行するには:

script_1.sh &&
script_2.sh &&
script_3.sh &&
script_4.sh &&
script_5.sh

コメントの強化

同時に実行する200のスクリプトがある場合(マシンBTWを停止する可能性があります)、次のスクリプトを使用します。

#!/bin/bash
for Script in my_folder/*.sh ; do
    echo bash "$Script" &
done

次のコマンドを使用して、スクリプト属性を実行可能に設定します。

chmod a+x /path/to/script.sh

スクリプトを初めて実行するときは、実行する200個のスクリプトの名前のみがエコーされます。適切な名前が選択されたら、スクリプトを編集して次の行を変更します。

    echo bash "$Script" &

に:

    bash "$Script" &

ここで回答したように、bashスクリプトを別のスクリプトから呼び出すには3つの方法があります。

  1. 他のスクリプトを実行可能に#!/bin/bashして、先頭に行を追加し、ファイルがある場所のパスを$PATH環境変数に追加します。その後、それを通常のコマンドとして呼び出すことができます。

  2. または、次のようにソースコマンド(エイリアスは。)を使用して呼び出しsource /path/to/scriptます。

  3. または、bashコマンドを使用して実行します/bin/bash /path/to/script

OPの場合、200スクリプトの1つ以上に#!/bin/bashファイルのシバンの最初の行が含まれていませんでした。そのため、オプション3.を使用する必要がありました。


同時に実行される200のスクリプト

それらが「同時に実行されている」かどうかについてのコメントがありました。典型的な8 CPUシステムでは、25のスクリプトが同時に1つのCPUを共有しますが、タイムスライス(ミリ秒で測定)がなくなるまで一度に1つのスクリプトのみが実行されます。その後、次のジョブはミリ秒の公平なシェアを受け取り、次に次のジョブなどを受け取ります。

大まかに言えば、200個のジョブが8つのCPUで「同時に」実行されているのではなく、同時に実行されていると言えます。つまり、CPUあたり25個のジョブに相当します。

スレッドstates.png

上記の画像と以下のLinuxカーネルスケジューラからのコメント

タイムスライス.png


ありがとうございます。実際のケースでは、実行するスクリプトが200以上あります。それで、1つのコマンドで(つまり、ファイル名を書き込まずに)すべてを実行できる方法はありますか?
aaaaa

@aaaaa 200スクリプトの回答を変更しました。
WinEunuuchs2Unix

ありがとう。それはうまくいきます。私があなたの最後の行に追加しなければならなかった唯一のものは「bash」でした。そうでない場合、「許可が拒否されました」。
aaaaa

1
@aaaaa実際に200以上のすべてのスクリプトを同時に実行することを希望しますか、それとも、より少ない数(たとえば、10)を同時に実行し、他のスクリプトが1つ以上の終了時に実行するためにキューに入れられるようにしますか?現在実行中のスクリプトの数がその数を下回っていますか?(このようなソリューションに興味がある場合は、スクリプトの数、実行にかかる時間、スクリプトの種類などの情報を使用して質問を編集することをお勧めします。)
Eliah Kagan

@aaaaaフィードバックをありがとう。答えを更新してbash、スクリプトを呼び出すためのプレフィックスを含めました。
WinEunuuchs2Unix

3

これのためのツールがあります、読んでくださいman run-parts

たとえば、私はします:

 run-parts ${visorhome}/pbackup.d/

Palm Pilotバックアップスクリプトで。${visorhome}/pbackup.d/

01PopulateJpilot  02Extract_Pedometer  03URLs  04google  05Books  06Weight  07Sec  08Bkgm 50hardlinks

1
@ eliah-kagan「200以上のスクリプト」を「同時に」実行することは賢明ではありません。システムのストレステストを行うには良い方法かもしれません
ワルティネーター

いい視点ね。run-partsOPが要求したように、一度にすべてではなく逐次的にスクリプトを実行することについて言及したいと思うかもしれません。ただし、一度に200のスクリプトを実行しても、5を実行した場合と同じように機能することはほとんどありません。一度にすべてを実行しても問題が発生しない場合でも、不要な場合があります。私は、OPがこの点で彼らの好みを明確にするようにコメントしました。
Eliah Kagan

run-partsスクリプトを実行しません(名前にドットが含まれています:my_folder/*.sh
jfs

1
run-parts持っている 特定のvery_いくつかの奇妙な理由で、ファイル名の要件。拡張子付きのファイル名は起動しないので、ここでは機能しないと思います。
terdon

1

を使用して*.shmy_folderディレクトリ内のすべてのスクリプトを同時に実行するにはxargs

$ ls my_folder/*.sh | xargs -P0 -n1 bash

同時に実行されるスクリプトの数を以下に制限するには10

$ ls my_folder/*.sh | xargs -P10 -n1 bash

lsスクリプトでの出力を使用することは悪い習慣です。使用する方findがはるかに安全です。これが最初のアイテムです:mywiki.wooledge.org/BashPitfalls#for_f_in_.24.28ls_.2A.mp3.29
Joe

@ジョー一般的に、それは本当です。この特定のケースでは問題は発生しません。
jfs

それはあなたがすでにそれについて知っているからです。後でここに来る人々はそうでないかもしれません。
Joe

@ジョーは盲目的にドグマをフォローしないでください。あなたの場合のトレードオフは何であるかよりも、1つのオプションが別のオプションよりも優れていることを自分で考えてください。
jfs

それは教義ではありません。私はそれらに寛容です。しかし、lsが放出できるものを見てきました。人間が読み取れる出力の解析は信頼できません。開発者が守るべきインセンティブがない
Joe
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.