마지막으로 중단한 부분부터 로그 파일을 계속 읽으세요.

마지막으로 중단한 부분부터 로그 파일을 계속 읽으세요.

일정 기간이 지나면 지속적으로 업데이트(새 줄 추가)되는 로그 파일이 있습니다.

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로 대체했습니다 . 추가 처리가 필요한 경우 출력을 명령으로 파이프할 수 있습니다.grepawk

답변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 }

관련 정보