서버 로그가 있고 서버가 시작되면 로그 파일에 특정 텍스트 줄을 출력합니다. 서버가 시작된 후에 명령을 실행하고 싶기 때문에 다음과 같이 합니다.
tail -f /path/to/serverLog | grep "server is up" ...(now, e.g., wget on server)?
이를 수행하는 가장 좋은 방법은 무엇입니까?
답변1
간단한 방법은 awk입니다.
tail -f /path/to/serverLog | awk '
/Printer is on fire!/ { system("shutdown -h now") }
/new USB high speed/ { system("echo \"New USB\" | mail admin") }'
예, 둘 다 커널 로그의 실제 메시지입니다. Perl을 사용하는 것이 더 우아할 수 있으며 tail의 필요성을 대체할 수도 있습니다. Perl을 사용하면 다음과 같습니다.
open(my $fd, "<", "/path/to/serverLog") or die "Can't open log";
while(1) {
if(eof $fd) {
sleep 1;
$fd->clearerr;
next;
}
my $line = <$fd>;
chomp($line);
if($line =~ /Printer is on fire!/) {
system("shutdown -h now");
} elsif($line =~ /new USB high speed/) {
system("echo \"New USB\" | mail admin");
}
}
답변2
한 가지 가능성만 찾고 있고 awk
or 를 사용하는 대신 대부분 셸에 머물고 싶다면 perl
다음을 수행할 수 있습니다.
tail -F /path/to/serverLog |
grep --line-buffered 'server is up' |
while read ; do my_command ; done
my_command
...매번 실행됩니다."서버가 시작되었습니다grep
" 가 로그 파일에 나타납니다. 여러 가지 가능성 으로 case
.while
대문자를 사용하면 어떤 로그 파일이 순환되는지 주의를 기울여야 합니다 -F
.tail
즉현재 파일의 이름이 바뀌고 동일한 이름의 다른 파일이 이를 대체하는 경우 tail
새 파일로 전환됩니다.
이 --line-buffered
옵션은 grep
버퍼가 각 라인 후에 플러시되도록 지시합니다. 그렇지 않으면 제 my_command
시간에 도착하지 못할 수 있습니다(로그에 적절한 크기의 라인이 있다고 가정).
답변3
이상하게도 multitail
이 기능을 즉시 사용할 수 있는 유틸리티에 대해 언급한 사람은 아무도 없습니다. 사용 예 중 하나:
ping 명령의 출력을 표시하고 시간 초과가 나타나면 현재 로그인된 모든 사용자에게 메시지를 보냅니다.
multitail -ex timeout "echo timeout | wall" -l "ping 192.168.0.1"
당신은 또한 볼 수 있습니다다른 예시용법 multitail
.
답변4
세게 때리다일을 스스로 할 수 있다
얼마나 간단하고 읽기 쉬운지 살펴보겠습니다.
mylog() {
echo >>/path/to/myscriptLog "$@"
}
while read line;do
case "$line" in
*"Printer on fire"* )
mylog Halting immediately
shutdown -h now
;;
*DHCPREQUEST* )
[[ "$line" =~ DHCPREQUEST\ for\ ([^\ ]*)\ ]]
mylog Incomming or refresh for ${BASH_REMATCH[1]}
$HOME/SomethingWithNewClient ${BASH_REMATCH[1]}
;;
* )
mylog "untrapped entry: $line"
;;
esac
done < <(tail -f /path/to/logfile)
bash 를 사용하지 않더라도 regex
매우 빠를 수 있습니다!
하지만세게 때리다+sed매우 효율적이고 흥미로운 탠덤입니다
그러나 부하가 높은 서버의 경우 sed
매우 빠르고 확장 가능하기 때문에 다음을 자주 사용합니다.
while read event target lost ; do
case $event in
NEW )
ip2int $target intTarget
((count[intTarget]++))
...
esac
done < <(tail -f /path/logfile | sed -une '
s/^.*New incom.*from ip \([0-9.]\+\) .*$/NEW \1/p;
s/^.*Auth.*ip \([0-9.]\+\) failed./FAIL \1/p;
...
')