回答:
この操作には一時ファイルを使用する必要があると思うので&&
、grepが次のような一致を示す終了ステータスを返した場合にのみ、オペレーターを使用してメールコマンドを実行できます。
TMPFILE=`mktemp /tmp/mailqgrep.XXXXXX`; mailq | egrep 'rejected|refused' -A5 -B5 > "$TMPFILE" && mail -s 'dd' email@email < "$TMPFILE"; rm "$TMPFILE"
一時ファイルがどこかに貼り付いていることを気にせず、静的な名前を使用できる場合は、特別な命名と削除をスキップできます。
mailq | egrep 'rejected|refused' -A5 -B5 > /tmp/mailqgrep && mail -s 'dd' email@email < /tmp/mailqgrep
編集:glennの答えを見た後、私はこれでもう少し遊んで、明らかに$()
構文を使用して変数を割り当てるとコマンドの終了コードが返されるので、文字列の長さに使用したテストをスキップして代わりに使用できます。ここでは、すべて1つのコマンドに含まれています。
data=$(mailq | egrep 'rejected|refused' -A 5 -B 5) && mail -s 'dd' email@email <<< "$data"
編集2:サイモンの答えを見た後、mail
プログラムをチェックアウトしました。デフォルトで彼が説明する方法では動作しませんが、そのためのオプションがあります。manページから:
-E
送信メッセージの最初または唯一のメッセージ部分にテキストが含まれていない場合、メッセージを送信せずにサイレントに破棄し、プログラムの起動時にskipemptybody変数を効果的に設定します。これは、cron(8)によって開始されたスクリプトからメッセージを送信するのに便利です。
これを可能にする:
mailq | egrep 'rejected|refused' -A 5 -B 5 | mail -E -s 'dd' email@email
mktemp
が引用を必要とするものを返さないのであれば、その編集は不要です。
glob(split(var))
。ここで単語分割やファイルグロブ拡張は必要ないので、それらを要求しないでください。また、このサイトで正しい方法を示す必要があります。
zsh
と、実際にいない私は彼らのためにお願いしない限り、このようなケースではグロブや単語分割を取得しますが、ここでの回答のためにではなく、原則のうち引用ターゲット環境を知ることは結構です。
出力を変数に保存し、文字列の長さがゼロ以外の場合にメールコマンドを呼び出すことができます。
data=$(mailq | egrep 'rejected|refused' -A 5 -B 5)
[[ -n "$data" ]] && mail -s 'dd' email@email <<< "$data"
1行の場合、2つのコマンドをセミコロンで結合します。
オプションmail
とともに使用し-E
ます。私のMacでは、MAIL(1)は-E
フラグが空の本文を含む電子メールを送信しないと言います。
-E本文が空のメッセージを送信しません。これは、cron(8)スクリプトからエラーをパイプするのに役立ちます。
私のMacでは、次のテストを実行しました。ファイルfile_does_exist
は存在しますが、ファイルは存在しないことに注意してくださいfile_does__not_exist
。
これは私に電子メールを送信します:
$ ls file_does_exist | egrep 'file' -A5 -B5 | mailx -E -s 'test' stefan@example.org
これはしません。コマンドls file_does_not_exist | egrep ...
は出力を生成しないことに注意してください。
$ ls file_does_not_exist | egrep 'file' -A5 -B5 | mailx -E -s 'test' stefan@example.org
ls: file_does_not_exist: No such file or directory
この特定のケースでは、あなたの場合はmail
サポート-E
オプション、それを使用しています。一般的な場合、1文字を読み取ろうとすることができます。ある場合は、後処理コマンドを開始し、ファイルの残りからその文字をフィードします。
pipe_if_not_empty () {
a=$(dd bs=1 count=1 2>/dev/null; echo .) # read at most one character
if [ "$a" != "." ]; then # if there were two characters,
{ printf %s "${a%.}"; # then output the first character
cat; } | # and the rest of the input
"$@" # into the specified program
fi
}
mailq | egrep 'rejected|refused' -A 5 -B 5 |
pipe_if_not_empty mail -s 'dd' email@email
の便利な使用法に注意してくださいcat
。を追加echo .
すると、入力の最初の文字が改行であってもこの関数が機能します($(…)
構造体が端末の改行を削除することに注意してください)。
ほとんどのシェル(zsh以外、私が知る限り)では、ファイルがヌル文字で始まる場合、このコードは空であると見なします。それを修正することは、読者の課題として残されています。(ヒント:od
最初のサブシェルで使用し、最初のprintf
バイトを出力します。)(解決策:パイプが空かどうかを確認する方法)ファイルが現在の有効な文字ではないバイトで始まる場合、同じ問題が発生する可能性がありますロケール; このコードをで実行すると、簡単に修正できますLC_ALL=C
。
read
これを使用してこれを簡素化できますか?
read
ポータブルshでは、空の最初の行と空のファイルを区別できないと思います(bash、kshまたはzshでは可能かもしれません)。