シェルコマンドでstdoutとsterrと正しいパイプ終了状態をキャプチャする方法は?

シェルコマンドでstdoutとsterrと正しいパイプ終了状態をキャプチャする方法は?

私は次のことができるようにしたいです。

command 2>&1 | shell_script.sh "subject line"

実行の stdout と sterr がcommandパイプで接続され、shell_script.sh電子メール本文に送信されます。私がやりたいことは、command 2>&1電子メールの件名に正しい作業状態を追加できるようにするための終了状態です。現在の実装では常にcommand 2>&1when piping${PIPESTATUS[0]}に設定されます0。ただし、そのエントリを削除すると、2>&1stderr出力は電子メール本文にパイプされません。いくつかの他のバリエーションを試しましたが、まだ把握できません。

次は私のものですshell_script.sh

#!/usr/bin/env bash
SUBJ="$@"
read EMAIL_BODY
jobsuccess=${PIPESTATUS[0]}

if [ $jobsuccess -eq 0 ]  # Job succeeded
then
        echo $EMAIL_BODY | mail -s "$SUBJ Success" [email protected]
else
        echo $EMAIL_BODY | mail -s "$SUBJ Fail" [email protected]
fi

答え1

#!/bin/bash

subject="subject line"

tmpfile=$(mktemp)
trap 'rm -f "$tmpfile"' EXIT

if command >"$tmpfile" 2>&1; then
    subject+=" Success"
else
    subject+=" Failure"
fi

mail -s "$subject" [email protected] <"$tmpfile"

したがって、出力を一時ファイルに保存してからファイルをメールで送信します。送信する前に、コマンドの終了状態に応じてタイトル行を設定します。 2つのスクリプトは必要ありません。

PIPESTATUSパイプラインがまだ実行を完了していないため、パイプラインの内部にアクセスできません。さらに、独自の環境で実行されるため、外部スクリプトにはどのような状況でもアクセスできません。

通常のコマンドで入力をパイプしてから、そのコマンドの終了状態を処理することもできません。パイプライン内の前のコマンドの終了ステータスは、パイプライン自体からアクセスできません。

あなたは何ですかできるdo は、成功または失敗を示すテキストを出力するコードでコマンドをラップします。このテキストは残りのデータと一緒にパイプされます(必要に応じて最後に追加情報として)。

{ if command 2>&1; then echo SUCCESS; else echo FAILURE; } | shell_script.sh

...そしてshell_script.sh存在

#!/bin/bash

subject="subject line"

tmpfile=$(mktemp)
trap 'rm -f "$tmpfile"' EXIT

cat >"$tmpfile"

if [[ $(tail -n 1 "$tmpfile") == *SUCCESS* ]]; then
    subject+=" Success"
else
    subject+=" Failure"
fi

sed '$d' "$tmpfile" | mail -s "$subject" [email protected]

最後の行にアクセスするには、データを一時ファイルに保存する必要があります(これはデフォルトでcat読み取られる標準入力を使用して行われます)。次に、成功するかどうかを決定し、それに応じてテーマを設定します。これにより、最後の行が削除されたデータがメールに送信されます。

別のオプションはメールスクリプトを実行することです。後ろにコマンドを実行してから(パイプラインのコマンドが同時に実行される)、終了ステータスをコマンドライン引数として渡します。

command >command.log 2>&1
shell_script.sh "$?" <command.log
rm -f command.log

スクリプトは次のとおりです。

#!/bin/bash

subject="subject line"

if [[ $1 == 0 ]]; then
    subject+=" Success"
else
    subject+=" Failure"
fi

mail -s "$subject" [email protected]

この場合、メールで送信されるデータは標準入力を介して渡され、mailユーティリティはデフォルトでそれを読み取ります(cat前の例と同様)。

関連情報