bash入門:xargsを利用した関数の並列実行

スポンサーリンク
bash入門:xargsを利用した関数の並列実行 ノウハウ
bash入門:xargsを利用した関数の並列実行
この記事は約7分で読めます。
よっしー
よっしー

こんにちは。よっしーです(^^)

今日は、bashにおけるxargsを利用した関数の並列実行についてご紹介します。

スポンサーリンク

背景

bashにおけるxargsを利用した関数の並列実行について調査する機会があったので、そのときの内容を備忘として残しました。

この記事のソースは下記のサイトにアップしています。

実行環境について

実行環境は下記の記事を参考にお願いします。

概要

本記事では、xargsを利用した関数の並列実行をしています。元となるソースは、前回記事のロギングのコードを利用しています。

作成ファイル一覧

下記のファイルを作成しました。

        new file:   local/work/13_xargs/13_xargs.sh

13_xargs.sh

#!/usr/bin/env bash

set -euCo pipefail

ESC="$(printf '\033')" # \e や \x1b または $'\e' は使用しない
LOG_OUT=./stdout.log
LOG_ERR=./stderr.log
readonly ESC LOG_OUT LOG_ERR

exec 1> >(tee -a "$LOG_OUT")
exec 2> >(tee -a "$LOG_ERR")

function log_info() {
    local log_msg
    log_msg=$(gen_log_msg '32' 'INFO' "$*")
    echo "${log_msg}"
}

function log_debug() {
    local log_msg
    log_msg=$(gen_log_msg '34' 'DEBUG' "$*")
    echo "${log_msg}"
}

function log_warn() {
    local log_msg
    log_msg=$(gen_log_msg '33' 'WARN' "$*")
    echo "${log_msg}"
}

function log_err() {
    local log_msg
    log_msg=$(gen_log_msg '31' 'ERROR' "$*")
    echo "${log_msg}" >&2
}

function gen_log_msg() {
    local prefix
    prefix=$(printf "${ESC}[%dm%5s${ESC}[m\n" "$1" "$2" )
    printf "%s\t[%s]\t%s" "$(date '+%Y/%m/%d %H:%M:%S.%3N')" "$prefix" "$3"
}

function trap_err() {
    error_status=$?
    msg=$(printf "エラー発生 \$?=%d %s %s:%d" ${error_status} "${BASH_SOURCE[0]}" "${FUNCNAME[1]}" ${BASH_LINENO[0]})
    log_err "${msg}"
}

function trap_exit() {
    msg=$(printf "終了時の処理 %s %s:%d" "${BASH_SOURCE[0]}" "${FUNCNAME[1]}" ${BASH_LINENO[0]})
    log_debug "${msg}"
}

function poc_run() {
    log_info "poc $1"
}

trap trap_err ERR

trap trap_exit EXIT

log_debug "$(which bash)"

log_debug "$(bash --version)"

export -f poc_run log_info log_err gen_log_msg
seq 1 20 | xargs -P "$(nproc)" -I{} bash -c "poc_run {}"

# 標準エラーへの出力確認用
ls dummy.txt

echo "ここは表示されない"

動作確認

下記のコマンドを実行します。

make build

make up

make login

cd 13_xargs

chmod +x 13_xargs.sh

./13_xargs.sh

下記のような出力になることを想定しています。

解説

13_xargs.sh

このBashスクリプトは、ログ出力とエラーハンドリングを含むサンプルのシェルスクリプトです。以下に、各部分の解説を行います。

  1. #!/usr/bin/env bash: スクリプトのシバン行。これは、このスクリプトがBashで実行されることを示しています。
  2. set -euCo pipefail: スクリプトのオプションの設定です。
  • -e: エラーが発生した場合にスクリプトを即座に終了します。
  • -u: 未定義の変数が使用された場合にエラーとして扱います。
  • -o pipefail: パイプの途中でエラーが発生した場合にもスクリプトを終了します。
  1. ESC="$(printf '\033')": ANSIエスケープシーケンスを表す変数 ESC を定義しています。
  2. LOG_OUT=./stdout.log および LOG_ERR=./stderr.log: 標準出力と標準エラー出力のログファイルのパスを定義しています。
  3. readonly ESC LOG_OUT LOG_ERR: ESC, LOG_OUT, LOG_ERR を読み取り専用に設定します。
  4. exec 1> >(tee -a "$LOG_OUT") および exec 2> >(tee -a "$LOG_ERR"): 標準出力および標準エラー出力をそれぞれ tee コマンドにパイプし、ログファイルに追記するように設定します。
  5. ログ関数:
  • log_info, log_debug, log_warn, log_err: 指定されたメッセージに応じたログメッセージを生成し、それを標準出力または標準エラー出力に出力します。
  • gen_log_msg: ログメッセージのプレフィックスを生成します。
  1. trap_err および trap_exit: エラーおよびスクリプト終了時に実行されるトラップ関数。エラーメッセージや終了時のメッセージをログに記録します。
  2. poc_run: サンプルの関数。引数として渡された値をもとにログメッセージを生成します。
  3. trap trap_err ERR および trap trap_exit EXIT: エラーおよびスクリプト終了時に対応するトラップ関数を設定します。
  4. log_debug "$(which bash)" および log_debug "$(bash --version)": Bashの実行パスとバージョン情報をデバッグログに出力します。
  5. export -f poc_run log_info log_err gen_log_msg: サブシェルで実行されるコマンドで関数を利用できるように関数をエクスポートします。
  6. seq 1 20 | xargs -P "$(nproc)" -I{} bash -c "poc_run {}": 1から20までの数字を生成し、それを複数のプロセスで同時に処理します。各プロセスは poc_run 関数を呼び出して、対応する数値を引数として渡します。
  7. ls dummy.txt: 標準エラー出力への出力を確認するためのダミーコマンド。エラーを意図的に発生させます。
  8. echo "ここは表示されない": 上記の ls dummy.txt でエラーが発生した場合、この行以降のコードは実行されません。エラーがない場合は、このメッセージが表示されます。

おわりに

今日は、bashにおけるlogging(ロギング)についてご紹介しました。

よっしー
よっしー

何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。

それでは、また明日お会いしましょう(^^)

コメント

タイトルとURLをコピーしました