システムサービスSTDERRをコマンド(sendmail)にリダイレクトする

システムサービスSTDERRをコマンド(sendmail)にリダイレクトする

以前によく聞いていた質問のようですが、いくら探してもいませんね。

私のパッケージを更新するタイマーで実行されるシステムサービスがあります。ssmtpサービスにエラーが発生するたびに電子メールを受信したいと思います。

端末からrootとして実行すると機能します。

 # /root/bin/update 2> >(printf "Subject: ERROR from update.service\n\n$(cat -)" | sendmail [email protected])
Updating package lists... Done!
Updating packages... Done!
Removing old packages... Done!
Cleaning up... Done!
Updating dotfiles... FAILED!
Updating bpytop... Done!
Updating global npm packages... Done!

失敗した部分がSTDERRを送信し、エラーが疑似ファイルにキャプチャされました>()printf "...$(cat -)"ストリームの先頭にトピックを追加します。本文がstderrであるEメールを受け取りました。かなり滑らかでしたか?

update.serviceから送信されたEメールスクリーンショット

私がしたいサービスはこれです。デフォルトでは、標準出力はログに出力されますが、標準エラーは私が選択したコマンドにリダイレクトされます。私はこれを最初に試しました:

ExecStart=/root/bin/update 2> >(printf "Subject: ERROR from update.service\n\n$(cat -)" | sendmail [email protected])

ただし、エラーは依然としてssmtpの代わりにジャーナルに送信されます。私はsystemdがstderrを傍受して指定された場所に送ると思いました。StandardError=。このStandardError=オプションを使用すると、stderrをファイル記述子またはファイルに送信できるため、次のように試しました。

ExecStart=/root/bin/update
StandardError=file:>(printf "Subject: ERROR from update.service\n\n$(cat -)" | sendmail [email protected])

そして

StandardError=fd:printf "Subject: ERROR from update.service\n\n$(cat -)" | sendmail [email protected]

役に立たない。 StandardErrorは、sendmailを指す名前付きパイプに送信できます。ここまでやろうと思ったら、やっぱり諦めてここまで来ました。

編集する: また、電子メールを送信する更新スクリプトに bash 関数を作成し、スクリプト内の各コマンドの stderr をその関数にリダイレクトすることも検討しました。しかし、私はスクリプト自体でSTDERRのターゲットをハードコーディングするのではなく、システムレベルのソリューションを探しています。

答え1

私は考えられる解決策を思いついた。 stderrをファイルに書き込むそれから送料を使用してくださいExecStartPost=。また、次のコマンドをラップしないと、システムサービスファイルが正しくリダイレ​​クトされないことがわかりました/bin/bash -c ''

ExecStartPre=/bin/rm -f /root/update.err
ExecStart=/bin/bash -c '/root/bin/update 2>/root/update.err'
ExecStartPost=/bin/bash -c 'test -f /root/update.err && printf "Subject: ERROR from update.service\n\n$(cat /root/update.err)\n" | sendmail [email protected]'

源泉:たとえば、ExecStartでSystemdサービスの標準出力をシェルにパイプする方法です。大きな打撃を受けましたか?

関連情報