よっしー
こんにちは。よっしーです(^^)
今日は、seqとxargsを利用した並列処理をしたときの方法についてご紹介します。
背景
同時に同じ処理を実行する場面があり、seqとxargsを利用した並列処理を実施したので、そのときの処理内容を備忘として残しました。
実施環境の用意
下記のファイルを用意しました。proc.shに処理を記載しています。
└── proc.sh
proc.sh
#!/usr/bin/env bash
now=$(date "+%Y%m%d%W_%H%M%S")
sh_name=$(basename "$0")
arg01=$1
log_dir=${sh_name%.sh}/${now}
[ ! -e "${log_dir}" ] && mkdir -p "${log_dir}"
{
echo now : "$now"
echo log : "$log_dir"
echo sh : "$sh_name"
echo seq : "$arg01"
} > "${log_dir}/${arg01}.log"
動作確認
下記のコマンドを実行します。
seq 10 | xargs -P $(nproc) -I{} -t sh -c "bash proc.sh {}"
データ確認
下記のコマンドを実行します。
tree proc
下記のようにデータがあれば、構築成功です。
% tree proc
proc
└── 2023082734_131316
├── 1.log
├── 10.log
├── 2.log
├── 3.log
├── 4.log
├── 5.log
├── 6.log
├── 7.log
├── 8.log
└── 9.log
解説
proc.sh
このスクリプトは、Bashシェルスクリプトで書かれており、主に次の処理を行います。
- 現在の日時情報とスクリプトの情報を収集して変数に格納します。
- ログディレクトリを作成します(存在しない場合のみ)。
- 変数に収集した情報を書き込んだログファイルを生成します。
スクリプトの各行を詳しく説明します:
#!/usr/bin/env bash
: この行は、スクリプトがBashシェルで実行されることを示しています。now=$(date "+%Y%m%d%W_%H%M%S")
:date
コマンドを使用して現在の日時情報を取得し、指定されたフォーマットに従って整形して変数now
に格納します。ここでは年月日と週番号、および時分秒が含まれるフォーマットが使用されています。sh_name=$(basename "$0")
: 変数sh_name
には、スクリプトのファイル名(拡張子を含まない)が格納されます。$0
はスクリプト自体へのパスを示す特殊な変数です。basename
コマンドはパスからファイル名を取得します。arg01=$1
: 変数arg01
には、スクリプト実行時に渡された第1引数(コマンドライン引数)が格納されます。log_dir=${sh_name%.sh}/${now}
:log_dir
変数には、ログディレクトリのパスが格納されます。このパスは、スクリプトのファイル名から拡張子.sh
を取り除いたものと、先ほど取得した日時情報を連結して生成されます。[ ! -e "${log_dir}" ] && mkdir -p "${log_dir}"
: ログディレクトリが存在しない場合、この行はそのディレクトリを作成します。[ ! -e "${log_dir}" ]
は、ファイルやディレクトリが存在しない場合に真となる条件式です。&&
は前のコマンドが成功した場合にのみ、次のコマンドを実行するための論理演算子です。mkdir -p "${log_dir}"
はディレクトリを再帰的に作成するコマンドです。echo now : "$now"
などの行: これらの行は、各情報をログファイルに書き込むためのコマンドです。{}
内に含まれるコマンドは、まとめて1つのファイルにリダイレクトされます。> "${log_dir}/${arg01}.log"
は、まとめたコマンドの出力をログファイルに書き込むためのリダイレクトです。
最終的に、このスクリプトは、ログファイルに次の情報を記録します:
- 現在の日時情報
- 生成されたログディレクトリのパス
- 実行中のスクリプトファイルの名前
- スクリプト実行時に渡された第1引数
これによって、スクリプトの実行ごとに異なる日時のログファイルが作成され、実行時の情報が記録されます。
seq 10 | xargs -P $(nproc) -I{} -t sh -c “bash proc.sh {}”
このコマンドは、Linuxのシェル環境で動作するコマンドラインのパイプラインです。各部分を解説します。
seq 10
: これは、1から10までの整数を生成するコマンドです。seq
コマンドは指定された範囲の整数を順に出力します。|
: パイプ演算子で、前のコマンドの出力を次のコマンドの入力として渡します。xargs -P $(nproc) -I{} -t sh -c "bash proc.sh {}"
:xargs
: 一連の引数を受け取り、それらを別のコマンドに渡すためのコマンドです。-P $(nproc)
: 並列実行のためのオプションです。nproc
コマンドはシステムの利用可能なプロセッサ数を返し、それを使って並列実行の数を指定しています。-I{}
: 渡された引数を後続のコマンドの中で{}
に置換します。-t
: 実行されるコマンドを表示します。sh -c "bash proc.sh {}"
: 渡された引数を使って、新しいシェルスクリプトを実行します。proc.sh
というスクリプトを実行し、引数を渡します。
総合すると、このコマンドは以下のことを行います:
seq 10
によって1から10までの整数が生成されます。xargs
はそれぞれの整数を並列で処理するため、nproc
で取得したプロセッサ数だけの並列実行を行います。- 各整数が
-t sh -c "bash proc.sh {}"
として渡され、proc.sh
というスクリプトがそれぞれの整数を引数として実行されます。
つまり、このコマンドは proc.sh
というスクリプトを、1から10までの整数を並列で処理しながら実行するものです。
おわりに
今日は、seqとxargsを利用した並列処理をしたときの方法についてご紹介しました。
よっしー
何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)
コメント