👋

Shellを使ったプロセスの非同期実行

2024/09/02に公開

Shellを使ったプロセスの非同期実行

シェルをマルチプロセスで動かす方法ってどんなんがあるか気になったので調査。

&バックグラウンド実行をwaitを使う

  • プロセスをバックグラウンドで実行するためにアンパサンドをつける
  • 直後に$!でプロセスIDを取得
  • wait pid を使ってプロセスを待つ
(
  sleep 3
  exit 0
) &
PID1=$!

(
  sleep 9
  exit 0
) &
PID2=$!

wait $PID1 $PID2

execとプロセス置換

  • exec 3< <(cp largefile1 largefile2 &) でプロセス置換を使って cp コマンドをバックグラウンドで実行しています。3< はファイルディスクリプター3を使用
  • wait <&3 でプロセスの完了を待つ
# 非同期に実行するプロセス置換
exec 3< <(cp largefile1 largefile2 &)

# 残りのスクリプトの処理を続ける
echo "ファイルのコピーをバックグラウンドで実行しています..."

# 他の処理をここに記述
# この間もファイルコピーは続行されます
sleep 10
echo "他の処理が完了しました。"

# 非同期処理が終了するのを待つ (プロセス置換の完了を待つ)
wait <&3

echo "ファイルのコピーが完了しました!"

xargs

  • echo "${files[@]}" | xargs -n 1 -P 4 -I {} cp {} ${destination_dir} で xargs を使って並行処理を実行
  • -n 1 は xargs が一度に1つの引数を処理するよう指示
  • -P 4 は最大で4つのプロセスを並行実行するよう
# コピー対象のファイルリストを作成
files=("file1.txt" "file2.txt" "file3.txt")

# コピー先ディレクトリ
destination_dir="backup/"

# 非同期に並行してコピーするために xargs を使用
echo "${files[@]}" | xargs -n 1 -P 4 -I {} cp {} ${destination_dir}

# 残りのスクリプトの処理を続ける
echo "ファイルのコピーをバックグラウンドで並行して実行しています..."

# 他の処理をここに記述
sleep 10
echo "他の処理が完了しました。"

echo "全てのファイルのコピーが完了しました!"

GNU Parallel

  • parallel cp {} {destination_dir} ::: "{files[@]}" で GNU Parallel を使ってファイルを並行してコピー
  • ::: の後に続く部分が並列で処理される入力
  • {} は並列処理中に各要素(ファイル名)
# コピー対象のファイルリストを作成
files=("file1.txt" "file2.txt" "file3.txt")

# コピー先ディレクトリ
destination_dir="backup/"

# GNU Parallel を使って非同期に並行してコピー
parallel cp {} ${destination_dir} ::: "${files[@]}"

# 残りのスクリプトの処理を続ける
echo "ファイルのコピーをバックグラウンドで並行して実行しています..."

# 他の処理をここに記述
sleep 10
echo "他の処理が完了しました。"

echo "全てのファイルのコピーが完了しました!"

リファレンス

Discussion