新しいことにはウェルカム

[技術] [電子工作] [ガジェット] [ゲーム] のメモ書き

シェルスクリプトでコマンドを並列実行する方法

ファイル毎に記録されたデータのバッチ処理を、シェルスクリプトで実行したりしています。

ファイルが大量にあった場合、1つのファイルの処理が終わるのを待ってから次のファイルの処理を行うといった、逐次処理をしているととても時間がかかることがありました。

何かいい方法はないかなぁと調べていたら「GNU parallel」という、シェルスクリプトでコマンドを並列実行できるものがあったので、今はそれを使っています。

GNU parallel

インストール

パッケージで配布されているのでインストール

$ sudo apt-get parallel

使い方

色々な書き方ができるのですが、一番汎用的な引数一覧をパイプで渡す書き方を紹介します。

<引数一覧> | parallel '<実行コマンド>'

<実行コマンド>で、引数が埋め込まれる箇所は{}で記載します。

$ seq 5 -1 1 | parallel --no-notice 'sleep {} && echo {}'
4
5
2
3
1
  • parallelを呼び出すと、毎回注意文が表示されるので、--no-noticeで表示しないようにします。
  • {}の位置に引数が埋め込まれます。
  • デフォルトでは、CPUのコア数だけ同時並列実行されます。
    • 手持ちの実行マシンはコア数が2だったので、結果は2つづつ同時並列実行され「4 5」「2 3」「1」の順で表示されました。

同時並列実行数

同時並列実行数は-jオプションで指定できます。

$ seq 5 -1 1 | parallel --no-notice -j 10 'sleep {} && echo {}'
1
2
3
4
5

同時並列実行数を10にしたので、5個全てが同時並列実行され、早く終わる1から順に表示されます。

実行結果取得

実行結果は変数$?に格納(0成功、1失敗)されます。

全て成功

$ echo -e "1\n2\n3" | parallel --no-notice 'sleep {} && echo {}'
1
2
3

$ echo $?
0

どれか1つでも失敗

$ echo -e "1\nA\n3" | parallel --no-notice 'sleep {} && echo {}'
sleep: `A': 無効な時間間隔です
Try 'sleep --help' for more information.
1
3

$ echo $?
1