트래픽이 거의 없는 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>
이제 한 줄에 하나의 이메일을 받았지만 내용이 없습니다.
tail -f access.log | xargs -I % | echo "%" | mail -s "Dateizugriff" <Destinationaddress>
작동하지 않습니다. 아무 일도하지. 다음도 작동하지 않습니다.
tail -f access.log | xargs | mail -s "Dateizugriff" <Destinationaddress>
그렇다면 작동하게 만드는 비결은 무엇입니까?
답변1
문제는 tail -f가 절대 종료되지 않는다는 것입니다. 단지 입력을 영원히 기다릴 뿐입니다. 따라서 파이프는 계속 열려 있고 메시지는 EOF를 수신하지 않으며 메시지가 "완료"될 때까지 기다립니다. 이는 결코 불가능합니다.
파이프에 다른 프로세스를 추가하는 것은 프로세스 중 적어도 하나가 종료되어 파이프를 파괴하지 않는 한 도움이 되지 않습니다.
로그에 추가된 각 줄을 별도의 메시지로 표시하려면 다음을 사용할 수 있습니다.
tail -f access.log | head -n 1 | mail -s "Dateizugriff" <user@domain>
Head는 한 줄을 읽은 후 종료되고, tail은 SIGPIPE를 수신한 후 종료되며, mail은 EOF를 수신한 후 계속해서 이메일을 보냅니다.
로그 항목이 여러 줄일 수 있지만 항상 마지막 줄을 식별할 수 있는 경우 sed 및 aq 조건을 사용하여 파이프를 끊을 수 있습니다.
첫 번째 단점은 메일 프로세스가 다음 줄이 도착할 때까지 기다리면서 영원히 중단된다는 것입니다.
두 번째 단점은 매번 프로세스가 완료되었음을 인식하고 전체 프로세스를 다시 시작해야 한다는 것입니다.
개인적으로 저는 휴면(약 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
또는 내 솔루션을 한 줄로 사용하려는 경우
tail -f access.log | awk -W interactive '/GET/{system("echo "$0" | mail -s \"New Access\" <Destinationaddress>")}'