xargs 活用術2

こんにちは。株式会社フィックスポイントのよしだです。

今回は、xargs コマンド活用術の発展編について発表があったため、ご紹介します。

前回の内容は下リンクより閲覧できますので、基本的な部分から読みたい!という方は是非覗いてみてください!

blog.fixpoint.co.jp

はじめに

今回の発表では、実務にて xargs コマンドが役立った例を紹介しています。

具体的には、弊社製品 Kompira cloud の構成ファイル生成を並列化できたため、xargs コマンドによる有用性を共有したようです。

その際に、xargs を使用すると手軽に処理の並列化ができるため、オススメなのだそうです😊

では早速、本題へと入りましょう!

for 文の並列化

最初に、下記のような for 文を xargs に置き換えて並列化してみます。

for src_file in $(find $src_dir -type f); do
  色々な処理
done

まず、 xargs 化 をします。
--max-args=1 で 1 引数毎 (ファイル毎) にコマンドを実行するという意味です。

find $src_dir -type f | xargs --max-args=1 <色々な処理.sh>

さらに、--max-procs オプションを使って並列化します。
引数により並列数を指定しますが、0 は CPU スレッド数と同じだけ並列化するという意味です。

find $src_dir -type f | xargs --max-args=1 --max-procs=0 <色々な処理.sh>

このような流れで xargs を使用した並列化ができました。

同じコマンドの並列化

次に、同じコマンドによるコマンド文の並列化を考えてみましょう。

例えば、このようなコマンド例文があったとします。

kustomize build src/namespaces          -o ${DIST}/namespaces.yml
kustomize build src/configs/config-maps -o ${DIST}/config-maps.yml
kustomize build src/configs/secrets     -o ${DIST}/secrets.yml
kustomize build src/apps                -o ${DIST}/apps.yml
kustomize build src/jobs                -o ${DIST}/jobs.yml

一見、先程と同様に xargs を使用してぱぱっと並列化できそうではありませんか?

ただ、よく見ると引数の複数個所がそれぞれ異なっていることが分かります。

それでは、どのように xargs を使えばよいでしょうか。

f:id:aqui_jasmine:20220224172112p:plain

前回の復習

さて、ここで一度前回の内容をおさらいしてみましょう。

前回、xargs コマンドを下記のようにご紹介しました。

xargs は、標準入力されたデータを行ごとコマンド引数に加えるコマンドです。

実はこの説明は、正しくはありつつもきちんと網羅した説明にはなっていません。申し訳ありません。

一体全体どういうこと?と思われた方も多いかと思いますので、詳しく説明していきます。

たしかに、大抵の場合 xargs を使う際の標準入力は

file1
file2
file3

のような形が多いです。
これは、find コマンドや ls コマンドなど、多くの shell コマンドは 1 行 1 情報を出力するようにできているためです。

そのため、xargs を使用すると、下記のように行ごとそれぞれに引数へ追加されます。

コマンド file1 file2 file3

ここまでが、前回ご紹介した内容です。

オプションによる違い

前回はご紹介していないオプションを使用することによって、少し異なる処理をすることが可能となります。
先程「網羅できていない」と言ったのはこの部分を指しています。

今回注目するオプションは、-n (--max-args) と -L (--max-lines) です。

一度、先程の例について --max-args=1--max-lines=1 を使用してみます。
すると、

コマンド file1
コマンド file2
コマンド file3

というように、どちらも1行ごとに別々のプログラムが起動されます。

ところが、下記のように1行に複数の引数が指定されていた場合は、異なったパターンによって実行されます。

file1 file2
file3 file4
--max-args=1 の場合
コマンド file1
コマンド file2
コマンド file3
コマンド file4
--max-lines=1 の場合
コマンド file1 file2
コマンド file3 file4

--max-args では引数ごと、--max-lines では一行ごとに処理が行われています。

もうお気づきの方もいらっしゃるとは思いますが、先程のコマンド例文を思い出してみましょう。

kustomize build src/namespaces          -o ${DIST}/namespaces.yml
kustomize build src/configs/config-maps -o ${DIST}/config-maps.yml
kustomize build src/configs/secrets     -o ${DIST}/secrets.yml
kustomize build src/apps                -o ${DIST}/apps.yml
kustomize build src/jobs                -o ${DIST}/jobs.yml

引数の複数個所がそれぞれ異なっているため、対応に困っていましたね。

そこで、ここでは --max-lines=1 を使うことにより、xargs 化できるようになる訳です!

xargs --max-lines=1 kustomize <<EOF
build src/namespaces          -o ${DIST}/namespaces.yml
build src/configs/config-maps -o ${DIST}/config-maps.yml
build src/configs/secrets     -o ${DIST}/secrets.yml
build src/apps                -o ${DIST}/apps.yml
build src/jobs                -o ${DIST}/jobs.yml
EOF

<<EOF の部分は、「ヒアドキュメント」で検索すると詳細が分かるかと思います。
IT用語辞典のリンクは下記の通りです。

e-words.jp

そして最初のように並列化します。

xargs --max-lines=1 --max-procs=0 kustomize <<EOF
build src/namespaces          -o ${DIST}/namespaces.yml
build src/configs/config-maps -o ${DIST}/config-maps.yml
build src/configs/secrets     -o ${DIST}/secrets.yml
build src/apps                -o ${DIST}/apps.yml
build src/jobs                -o ${DIST}/jobs.yml
EOF

以上が、xargs のオプションを使用した並列化の方法です。

ちなみに今回は、--max-args--max-lines , --max-procs 等の long options 形式を使用していますが、BSD 版 xargs にはこれらのオプションがなかったり名前が違うことがあります。

以下の対応する short option を使用した方が様々な環境で動かすことができます。

long option short option
--max-args -n
--max-lines -L
--max-procs -P

参加者の反応

今回の発表を聞いた参加者の反応です。

オプションを知らなかったため勉強になった方もいたようですね😊

また一番下にあるように、質問を Slack から投げかけたりすることも可能です!

基本的には毎発表ごとに質疑応答の時間もありますので、そこでみなさん自由に質問しています♪

f:id:aqui_jasmine:20220224213624p:plain

最後に

今回は、xargs 発展編として、手軽にシェルスクリプトで並列処理する方法をご紹介しました。

--max-lines を活用すれば、複数引数にも対応できるため、色々な場面で並列化が可能になります!

ぜひ、xargs を生かした並列化を試してみてくださいね。



株式会社フィックスポイントでは、一緒に働いてくれるメンバーを募集しています!

詳細は、こちらをご覧ください。