以前によく聞いていた質問のようですが、いくら探してもいませんね。
私のパッケージを更新するタイマーで実行されるシステムサービスがあります。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メールを受け取りました。かなり滑らかでしたか?
私がしたいサービスはこれです。デフォルトでは、標準出力はログに出力されますが、標準エラーは私が選択したコマンドにリダイレクトされます。私はこれを最初に試しました:
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サービスの標準出力をシェルにパイプする方法です。大きな打撃を受けましたか?