일정 기간이 지나면 지속적으로 업데이트(새 줄 추가)되는 로그 파일이 있습니다.
10분마다 파일에서 오류 메시지만 받습니다.
처음에는 모든 줄을 새 파일로 추출하고 "ERROR FOUND" 일치 패턴을 사용했습니다.앗.
하지만 10분 후에는 로그 파일에 새로운 줄이 더 추가되므로 로그 파일을 남겨둔 위치에서 읽어보고 싶습니다. 다시 처음부터 시작하고 싶지 않아요.
누구든지 나에게 최고의 코드나 스크립트를 제안할 수 있나요?
답변1
다음과 같은 파일 설명자에서 파일을 열면:
exec 3< /path/to/log/file
그런 다음 처리할 수 있습니다.
awk '...' <&3
awk
그러면 fd 3은 왼쪽 위치를 가리킬 것입니다 .
10분 후 동일한 셸 호출에서 다음 명령을 실행할 수 있습니다.
awk '...' <&3
새로운 데이터를 처리하기 위해 다시 명령을 내립니다.
다른 쉘 호출에서 읽기를 재개할 수 있도록 현재 위치를 저장하려면 ksh93
다음을 수행할 수 있습니다.
#! /usr/bin/env ksh93
file=/path/to/some-file
offset_file=$file.offset
exec 3< "$file"
[ -f "$offset_file" ] && exec 3<#(($(<"$offset_file")))
awk '...' <&3
echo "$(3<#((CUR)))" > "$offset_file"
또는 zsh를 사용하십시오.
#! /usr/bin/env zsh
zmodload zsh/system
file=/path/to/some-file
offset_file=$file.offset
exec 3< $file
[ -f "$offset_file" ] && sysseek -u 3 "$(<$offset_file)"
awk '...' <&3
echo $((systell(3))) > $offset_file
답변2
나는 Stéphane의 답변이 전체 파일을 계속해서 읽지 않기 때문에 좋아하므로 여기에 추가했습니다.세게 때리다(Linux에서) 그의 솔루션과 동일합니다(bash에는 내장된 기능 seek
이나 tell
성능이 없습니다). 댓글을 남기고 싶었는데 평판이 너무 낮네요.
LASTPOS=/tmp/saved_pos
exec 3< "$1"
test -f "$LASTPOS" && STARTPOS=$(($(<$LASTPOS)+1))
tail -c "+${STARTPOS:-1}" <&3 | grep "ERROR FOUND"
grep '^pos:' /proc/self/fdinfo/3 | cut -f2 > "$LASTPOS"
또한 일반적으로 더 빠르기 때문에 awk
명령을 a로 대체했습니다 . 추가 처리가 필요한 경우 출력을 명령으로 파이프할 수 있습니다.grep
awk
답변3
wc -l
나는 and 를 사용해 볼 것이다 tail
.
Bash를 사용하는 경우 다음과 같이 작동합니다.
#!/bin/bash
LASTLNFILE=/tmp/lastline # replace with a suitable path
test -f $LASTLNFILE && LASTLN=$(<$LASTLNFILE)
CURLN=$(wc -l $1 | cut -d' ' -f1)
if ((CURLN-LASTLN > 0)); then
tail -n $((CURLN-LASTLN)) $1
fi
echo $CURLN > $LASTLNFILE
PS 예를 들어 awk 프로그램 이전에 이것을 필터로 사용하십시오(이름을 "newlines.sh"라고 가정):
./newlines.sh <log_file> | awk -f <your_awk_program>`
위의 스크립트를 예로 사용하여 방법을 보여드리겠습니다.하지 마세요. 스크립트를 작성하고 나서 스크립트가 실행되는 동안 로그 파일이 업데이트되는 한 경쟁 조건에 취약하다는 것을 깨달았습니다.
순수한 AWK 접근 방식을 사용하는 것이 더 좋습니다.
#!/bin/awk
BEGIN {
lastlinefile = "/tmp/lastlinefile"
getline lastline < lastlinefile
}
NR > lastline && /ERROR FOUND/ {
# do your stuff...
print
}
END { print NR > lastlinefile }