備忘
要件
以下を満たしてAnsible Shellモジュールを使用したい
- Ansible Shellモジュールにstdout, stderrを正しく戻す
- かつ、途中経過を確認できる様にログファイルにもstdout, stderrを書き出す
- かつ、AIX環境(ksh)でも使える(汎用的)
exec で出力先をログフィルにするとShellモジュールに結果が戻せない。
全体に対して| teeを用いる対応では、stdoutとstderrを個別に扱うことが困難。
しかし、名前付きパイプを利用すれば要件を満たすことが可能。
ソリューション
名前付きパイプを使用する
task例
- name: "STDOUT, STDERRをリアルタイムでログに書き出すshellモジュール例"
shell: |-
LOGFILE="/tmp/logfile.log"
STDOUT_PIPE="/tmp/stdout_pipe.$$"
STDERR_PIPE="/tmp/stderr_pipe.$$"
mkfifo "$STDOUT_PIPE" "$STDERR_PIPE"
trap "rm -f '$STDOUT_PIPE' '$STDERR_PIPE'" EXIT
cat /dev/null > "$LOGFILE"
tee -a "$LOGFILE" < "$STDOUT_PIPE" &
tee -a "$LOGFILE" < "$STDERR_PIPE" >&2 &
exec > "$STDOUT_PIPE" 2> "$STDERR_PIPE"
set -x
処理本体
...
- 少し長いので複数行の変数としてどこかにまとめておいても良いでしょう。
- mkfifoコマンドで名前付きパイプを作成、execでstdout, stderrと接続、teeコマンドにてファイルに分岐させた上で、stdout, stderrに戻すといった流れ。
- trapを用いてスクリプト終了時に名前付きパイプも削除。
- 最新のshellの状況さえ分かれば良いだけならLOGFILEをつどnullクリアすればハウスキープもほぼ不要。
- set -xのデバックモード指定は、処理本体に影響がないことを確認の上、必要に応じて。