답변:
간단한 방법은 어색합니다.
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은 이것에 사용하기에 조금 더 우아 할 수도 있고 꼬리의 필요성을 대체 할 수도 있습니다. 펄을 사용한다면 다음과 같이 보일 것이다 :
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");
}
}
awk
한 줄로 짧고 쉽게 할 수 있는 솔루션을 좋아합니다 . 그러나 실행하려는 명령에 따옴표가있는 경우 약간 번거로울 수 있습니다. 파이프 라인 및 복합 명령을 사용하여 간단한 한 줄 솔루션을 허용하지만 결과 명령을 전달할 필요는 없습니다. 문자열로?
system()
명령 내에서 사용하기 위해 자유롭게 사용할 수 있습니다 .
tail -f /path/to/serverLog | grep "server is up" | head -1 && do_some_command
tail -n 0 -f /path/to/serverLog
파일의 마지막 0 줄을 읽은 다음 더 많은 줄이 인쇄 될 때까지 기다리는 것입니다.
당신은 단지 하나의 가능성을 찾고 사용하는 쉘에 주로 머물 것이 아니라 원하는 경우 awk
또는 perl
, 당신은 뭔가를 할 수 있습니다 :
tail -F /path/to/serverLog |
grep --line-buffered 'server is up' |
while read ; do my_command ; done
... 로그 파일에 my_command
" server is up "이 나타날 때마다 실행 됩니다 . 여러 가능성을 위해을 삭제하고을 grep
대신 사용할 수 case
있습니다 while
.
수도 -F
는 tail
로그 파일의 회전을 감시하도록 지시 합니다. 즉 , 현재 파일 이름이 바뀌고 동일한 이름을 가진 다른 파일이 대신 사용되면 tail
새 파일로 전환됩니다.
이 --line-buffered
옵션은 grep
모든 줄마다 버퍼를 플러시하도록 지시 합니다. 그렇지 않으면, my_command
로그에 적당한 크기의 선이 있다고 가정하여 적시에 도달하지 못할 수 있습니다.
--line-buffered
옵션 을 추가해야 grep
하거나 그렇지 않으면 라인 사이에서 출력을 플러시해야합니다. 그렇지 않으면 그냥 멈추고 my_command
도달하지 않습니다. 원하는 경우 ack
, 그것은이 --flush
플래그를; 원하는 경우로 ag
감싸보십시오 stdbuf
. stackoverflow.com/questions/28982518/…
do exit ;
. 잘 작동하는 것처럼 보였지만 꼬리는 끝나지 않았고 스크립트는 다음 줄로 이동하지 않았습니다. do
섹션 에서 꼬리를 막을 수있는 방법이 있습니까?
이 질문에 이미 답변 된 것으로 보이지만 더 나은 해결책이 있다고 생각합니다.
그보다는 tail | whatever
당신이 정말로 원하는 것이 있다고 생각합니다 swatch
. Swatch는 요청한 작업을 수행하고 로그 파일을보고 로그 라인을 기반으로 작업을 실행하도록 명시 적으로 설계된 프로그램입니다. 사용 tail|foo
하려면이 작업을 수행하기 위해 터미널을 적극적으로 실행해야합니다. 반면 견본은 데몬으로 실행되며 항상 로그를 감시합니다. 견본은 모든 Linux 배포판에서 사용할 수 있습니다.
나는 당신이 그것을 시도하는 것이 좋습니다. 드라이버의 뒷면에 못을 박을 수 있다고해서 꼭 그래야하는 것은 아닙니다.
내가 찾을 수있는 견본에 대한 최고의 30 초 자습서는 여기에 있습니다 : http://www.campin.net/newlogcheck.html
그것이 얼마나 간단하고 읽기 쉬운 지 봅시다 :
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
의 경우 매우 빠르고 확장 성이 뛰어 나기 때문에 원하는 경우 종종 다음을 사용합니다.
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;
...
')
그것이 내가 이것을 시작한 방법이지만 훨씬 더 정교 해졌습니다. 고려해야 할 몇 가지 사항 :
나는 이것의 라인을 따라 무언가를 사용한다 :
RELEASE=/tmp/${RANDOM}$$
(
trap 'false' 1
trap "rm -f ${RELEASE}" 0
while ! [ -s ${RELEASE} ]; do sleep 3; done
# You can put code here if you want to do something
# once the grep succeeds.
) & wait_pid=$!
tail --pid=${wait_pid} -F /path/to/serverLog \
| sed "1,10d" \
| grep "server is up" > ${RELEASE}
파일에 데이터가 tail
포함될 때까지 열린 채로 작동 ${RELEASE}
합니다.
(가) 번 grep
을 성공 :
${RELEASE}
되는 것${wait_pid}
프로세스를 종료 하다tail
참고 : 시작시 생성 할 sed
줄 수를 실제로 결정하고 해당 번호를 tail
제거하는 것이 더 정교 할 수 있습니다 . 그러나 일반적으로 10입니다.
tail -F
회전 로그 처리 - 즉my.log
전체되고으로 이동my.log.1
하고 프로세스는 새로운 생성my.log