ログファイルで行が変更されたときにメールを送信する、メールのtail -fパイピングが機能しない

ログファイルで行が変更されたときにメールを送信する、メールのtail -fパイピングが機能しない

トラフィックが少ないnginx access.logがあるので、アクセスするたびに電子メールを受信したいと思います。頑張った

tail -f access.log | cat

これはうまくいきます。だから、テールパイピングを使っても大丈夫そうです。

以下では何も起こりません。

tail -f access.log | mail -s "Dateizugriff" <Destinationaddress>

どちらもありません

tail -f access.log | grep --line-buffered '.*' | mail -s "Dateizugriff" <Destinationaddress>

...でもない

stdbuf -oL -eL  tail -f access.log | mail -s "Dateizugriff" <Destinationaddress>

もちろん動作します

echo "test" | mail -s "Dateizugriff" <Destinationaddress>

働く

それからxargsを試しました。

tail -f access.log | xargs -I % mail -s "Dateizugriff" <Destinationaddress>

1行に1つのメールを受け取りましたが、内容はありません。

tail -f access.log | xargs -I % | echo "%" |  mail -s "Dateizugriff" <Destinationaddress>

動作しません。何もしません。以下も機能しません。

tail -f access.log | xargs |  mail -s "Dateizugriff" <Destinationaddress>

では、うまくいく秘訣は何ですか?

答え1

問題は、tail -fが決して終了しないことです。ただ入力を永遠に待つだけです。したがって、パイプは開いたままであり、メッセージはEOFを受信せず、メッセージが「完了」するのを待ちます。これは決して不可能です。

パイプに別のプロセスを追加することは、プロセスの少なくとも1つが終了してパイプを破壊しない限り役に立ちません。

ログに追加された各行を別々のメッセージとして表示するには、次のようにします。

tail -f access.log | head -n 1 | mail -s "Dateizugriff" <user@domain>

Headは1行を読んだ後に終了し、tailはSIGPIPEを受信して​​から終了し、mailはEOFを受信した後に電子メールを送信し続けます。

ログエントリが複数行になる可能性がありますが、常に最後の行を識別できる場合は、sedおよびaq条件を使用してパイプを破棄できます。

最初の欠点は、メールプロセスが次の行が到着するのを待って永久に中断されることです。

2番目の欠点は、毎回プロセスが完了したことを認識し、プロセス全体を再起動する必要があることです。

個人的には、休眠(約60秒)を含むループ内で追加された行を見つけようとする繰り返しのシェルループを作成します。ファイルサイズが大きくなると、-fなしでtailを実行できるため停止しません。

繰り返す前に、nLineを現在の行番号に初期化します。リダイレクトは、wcがファイル名と数を報告するのを防ぐため、重要です。

nLine="$( wc -l < access.log )"

while : ; do
    NEW=$( tail -n +$(( 1 + nLine )) access.log )
    [[ "${#NEW}" -gt 0 ]] && {
        echo "${NEW}" | mail ....
        nLine=$(( nLine + $( wc -l <<<${NEW} ) ))
    }
    sleep 60
done

答え2

おそらく、システムが再起動されるたびに、この「監視」プロセスが自動的に開始されることを望むでしょう。systemdこれを行う合理的な方法です。

monitor_nginx_access.pathこれは、次の内容を含むファイルを作成することを意味します。

[Unit]
Description=Alert admin about access

[Path]
PathChanged=/absolute/path/to/access.log

そして提供する同じ名前でmonitor_nginx_access.service基本的に魔法を実行するシェルスクリプトの周りのラッパーが含まれています。

[Unit]
Description=Send mail when access log changes

[Service]
ExecStart=/absolute/path/to/mailscript.sh

どちらのファイルも次の場所に配置されます。/etc/systemd/システムまたは、インストールに管理者定義ユニットが必要なsystemd場合(マンページを参照)。

これにより、mailscript.sh次の内容が含まれます。

#!/bin/bash
MAILLINES=5  # how many of the last lines of access.log to mail
...

tail -n "$MAILLINES" /absolute/path/to/access.log | mail -s <your arguments here>

答え3

この回答を確認してください。https://stackoverflow.com/a/4657782/12332118 私はそれをテストし、それは私に効果的です。 systemdを使用せずに必要な操作を正確に実行します。

答え4

Max Müllerが接続したように、次のことができます。

tail -f access.log | grep --line-buffered GET | 
while read line 
do 
echo $line | mail -s New Access <Destinationaddress>
done

または、私のソリューションを1行で使用したい場合

tail -f access.log | awk -W interactive '/GET/{system("echo "$0" | mail -s \"New Access\" <Destinationaddress>")}'

関連情報