GNU parallelコマンドでシェルスクリプトの並列処理を設計する方法|xargsより高機能な並列実行とジョブ制御の実践

運営:リナックスマスター.JP(代表 宮崎智広)
HOME > Linux技術 リナックスマスター.JP(Linuxマスター.JP) > シェルスクリプト > GNU parallelコマンドでシェルスクリプトの並列処理を設計する方法|xargsより高機能な並列実行とジョブ制御の実践
「for ループで & バックグラウンド実行はしているけれど、エラーハンドリングが煩雑で本番環境には使いにくい——」
「xargs -P で並列化しているが、ジョブ数の上限制御や失敗したジョブの特定が難しい——」

こういった経験をした方は多いはずです。Linuxの標準機能(& + wait、xargs -P)でも並列処理は実現できますが、本番運用に耐える設計——ジョブ数制御・失敗時の自動停止・実行ログの保存——を組み込もうとすると途端に複雑になります。

この記事では、RHEL 9系/Ubuntu 24.04 LTSを想定環境として、GNU parallelコマンドの基本構文から本番向け設計パターンまでを解説します。GNU parallelは標準リポジトリからインストールできる外部ツールで、シェルスクリプトの並列処理を宣言的かつ堅牢に設計できます。

この記事のポイント

・GNU parallelは--jobsでジョブ数を制御し、xargs -Pより直感的に並列数を管理できる
・--halt now,fail=1で1件でも失敗したら全ジョブを即停止できる
・--joblongで各ジョブの終了コード・実行時間をCSV形式でファイルに保存できる
・--will-citeで確認プロンプトを抑制してcronから無人実行できる


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

GNU parallelとは — &+waitやxargsとの違い

GNU parallelはシェルコマンドを複数プロセスで並列実行するためのユーティリティです。2010年代から継続開発されており、RHEL 9・Ubuntu 24.04 LTSの標準リポジトリからインストールできます。

まず、既存の並列処理手法との差を整理しておきます。
手法 ジョブ数制限 エラーで全停止 実行ログ 出力混在対策
& + wait 手動実装が必要 手動実装が必要 なし なし(混在する)
xargs -P -P N で指定 不可 なし 混在する
GNU parallel --jobs N/% で指定 --halt で制御可 --joblog で保存 --line-buffer/--group
& + wait の並列処理でも「全体の終了を待つ」「pid を配列で管理する」などの実装は可能ですが、コードが煩雑になります。GNU parallelを使えば、同じことを宣言的に、かつ追加オプション1つで実現できます。

GNU parallelのインストールと基本構文

1. インストール方法

# RHEL 9 / CentOS Stream 9 / Rocky Linux 9 $ sudo dnf install parallel # Ubuntu 24.04 LTS / Debian $ sudo apt install parallel # バージョン確認 $ parallel --version # 出力例(環境により異なります) # GNU parallel 20231122

2. 基本構文

最もシンプルな形は parallel コマンド ::: 引数リスト です。:::(3つのコロン)が「このあとに引数を列挙する」という区切りです。

# 基本構文: parallel [オプション] コマンド ::: 引数1 引数2 ... parallel echo ::: A B C # 出力例(順不同・環境により異なります) # A # B # C # {}(中括弧)が引数の置換文字 parallel echo "Processing: {}" ::: A B C # Processing: A # Processing: B # Processing: C

引数置換文字には用途に応じたバリエーションがあります。

・{}:引数全体(ファイルパスならフルパス)
・{.}:拡張子を除いた部分(/var/log/app.log → /var/log/app)
・{/}:ディレクトリ部分を除いたファイル名(app.log)
・{//}:ディレクトリ部分のみ(/var/log)
・{#}:ジョブの通し番号(1, 2, 3 …)

本番向け設計パターン4選

1. --jobsでジョブ数を制御する

デフォルトはCPUコア数と同じ数のジョブを起動します。サーバーに負荷をかけたくない場合は明示的に制限します。

# 同時に4ジョブまで実行 parallel --jobs 4 'gzip -9 {}' ::: /var/log/app/2024-*.log # CPUコア数の50%以下に制限(例: 8コアなら最大4ジョブ) parallel --jobs 50% 'gzip -9 {}' ::: /var/log/app/2024-*.log # ファイルから引数リストを読み込む(:::: でファイル指定) find /var/log/app -name "*.log" -mtime +7 > /tmp/targets.txt parallel --jobs 4 'gzip -9 {}' :::: /tmp/targets.txt

2. --haltでエラー時に全ジョブを即停止する

バックアップ処理など「1件でも失敗したら全体を止めたい」ケースで有効です。

# --halt now,fail=1: 1件でも失敗したら実行中のジョブも即SIGTERM parallel --halt now,fail=1 'rsync -a {} backup01:/backup/' ::: /data/db /data/files /data/media # --halt soon,fail=1: 実行中のジョブは最後まで待ってから停止(より安全) parallel --halt soon,fail=1 'rsync -a {} backup01:/backup/' ::: /data/db /data/files /data/media

nowとsoonの選択は処理内容によります。データベースダンプなど途中で中断すると壊れる処理はsoonを使いましょう。

【注意】 --halt now,fail=1は実行中のジョブをSIGTERMで強制停止します。gzip圧縮中のファイルや書き込み途中のバックアップファイルが破損するリスクがあります。ファイル書き込みを伴う処理にはsoonを使うか、処理後に整合性チェックを入れてください。

3. --joblongで実行ログを保存する

本番スクリプトでは後から障害調査できるよう、各ジョブの実行結果をログに残すことが重要です。

JOBLOG="/var/log/parallel-compress-$(date +%Y%m%d).log" parallel --jobs 4 --halt soon,fail=1 --joblog "$JOBLOG" 'gzip -9 {}' ::: /var/log/app/2024-*.log # ログの形式(タブ区切り) # Seq Host Starttime JobRuntime Send Receive Exitval Signal Command # 1 : 1700000000.000 1.234 0 0 0 0 gzip -9 /var/log/app/2024-01-01.log # 失敗ジョブだけを抽出(Exitval != 0) awk 'NR>1 && $7 != 0 { print $9, "exit:", $7 }' "$JOBLOG"

4. --will-citeでcronから無人実行する

GNU parallelは初回起動時に「論文を引用してください」という確認プロンプトを表示します。これがcronで詰まる原因になるため、--will-citeで抑制します。

# NG: cronから実行すると確認プロンプトで止まる parallel --jobs 4 'gzip {}' ::: *.log # OK: --will-cite でプロンプトを抑制 parallel --will-cite --jobs 4 'gzip {}' ::: *.log # または: ~/.parallel/will-cite ファイルを作成しておく(恒久設定) mkdir -p ~/.parallel touch ~/.parallel/will-cite

実践スクリプト — ログファイルの一括圧縮バックアップ

シェルスクリプトをより体系的に設計したい方は、シェルスクリプト設計の実践入門もあわせてご覧ください。

ここまでのオプションを組み合わせた実践スクリプトを示します。

#!/bin/bash set -euo pipefail LOG_DIR="/var/log/app" ARCHIVE_DIR="/backup/logs" JOBLOG="/var/log/parallel-compress-$(date +%Y%m%d).log" MAX_JOBS=4 DAYS_OLD=7 # 7日以上前のログを圧縮対象リストに追加 find "$LOG_DIR" -name "*.log" -mtime +"$DAYS_OLD" > /tmp/compress_targets.txt # 対象ファイルが0件なら終了 if [ ! -s /tmp/compress_targets.txt ]; then echo "対象ファイルなし" exit 0 fi echo "圧縮対象: $(wc -l < /tmp/compress_targets.txt) 件" # GNU parallel で並列圧縮 + アーカイブディレクトリへ移動 parallel --will-cite --jobs "$MAX_JOBS" --halt soon,fail=1 --joblog "$JOBLOG" --progress 'gzip -9 {} && mv {}.gz '"$ARCHIVE_DIR"'/' :::: /tmp/compress_targets.txt echo "完了。ログ: $JOBLOG"

このスクリプトは以下の設計ポイントを満たしています。

・対象が0件なら早期終了(無駄な並列起動を防ぐ)
・--halt soon,fail=1でgzip失敗時は全体を停止(中途半端な状態を残さない)
・--joblogで各ファイルの処理結果を記録(後から失敗ファイルを特定できる)
・set -euo pipefailで変数ミスや予期しないエラーを早期検知

トラブルシュート

「GNU parallel will be cited...」のメッセージが出て止まる

cronから実行したとき標準エラーに次のメッセージが出て、処理が進まなくなる場合があります。

# このメッセージが標準エラーに出て確認を求められる # Academic tradition requires you to cite works you base your activities on. # 対処法1: スクリプトに --will-cite を付ける(推奨) parallel --will-cite --jobs 4 ... # 対処法2: ~/.parallel/will-cite ファイルを作成(恒久設定) mkdir -p ~/.parallel && touch ~/.parallel/will-cite

ジョブの出力が混在して読みにくい

複数ジョブが同時に標準出力に書き込むと行が混在します。

# --line-buffer: 1行単位でバッファリング。行の混在を最小化 parallel --line-buffer --jobs 4 'echo "job {}: done"' ::: 1 2 3 4 # --group(デフォルト動作): ジョブが完了するまで出力を保持して一括出力 # 出力は混在しないが、ジョブが長時間かかると表示が遅延する parallel --group --jobs 4 'long-running-cmd {}' ::: A B C

GNU parallelとxargs -Pの使い分け指針

状況 推奨
標準インストール環境のみで動かしたい xargs -P(外部ツール不要)
ジョブ数制御・エラー停止・実行ログが必要 GNU parallel
SSH経由で複数サーバーに並列実行 GNU parallel(--sshloginfile)
大量のstdinをパイプで並列処理 GNU parallel(--pipe)

本記事のまとめ

やりたいこと コマンド
ジョブ数を4つに制限して並列実行 parallel --jobs 4 cmd ::: args
1件失敗したら全ジョブを即停止 parallel --halt now,fail=1 cmd ::: args
各ジョブの実行ログをファイルに保存 parallel --joblog /tmp/log.csv cmd ::: args
進捗をリアルタイム表示しながら実行 parallel --progress cmd ::: args
cron実行時の確認プロンプトを抑制 parallel --will-cite cmd ::: args
出力の行混在を防いで読みやすくする parallel --line-buffer cmd ::: args
GNU parallelを使うと、& + waitで自分で実装していたジョブ数制御・エラー停止・ログ保存をオプション1つで実現できます。本番スクリプトに組み込む際は--will-citeを忘れずに付け、--joblogで障害調査の手がかりを残す設計を心がけてください。

現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、

シェルスクリプトの設計から本番自動化まで、ハンズオンで習得できる実践コースを公開しています。詳細はこちら >>

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録

運営

リナックスマスター.JP(代表 宮崎智広)

株式会社イーネットマーキュリーが運営するLinux教育サイトです。代表の宮崎智広は現役のLinuxサーバー管理者として20年以上の実務経験を持ち、累計3,100名以上のエンジニアを指導してきました。実践型のLinuxセミナーや無料マニュアルの配布を通じてLinux人材の育成に取り組んでいます。