연속 스트림을 'grep'하는 방법은 무엇입니까?


729

사용 가능합니까 grep연속 스트림 있습니까?

내가 의미하는 것은 일종의 tail -f <file>명령이지만 grep관심있는 줄만 유지하기 위해 출력이 있습니다.

나는 시도 tail -f <file> | grep pattern했지만 끝났을 grep때만 실행될 수있는 것처럼 보입니다 tail.


9
파일을 생성하는 프로그램이 출력을 플러시하지 않을 가능성이 높습니다.
Steve-o

tail -f file작품 (실시간으로 새로운 결과를 봅니다)
Matthieu Napoli

6
에 적합 할 unix.stackexchange.com
뤽 M

@Luc는 실제로 그렇게 생각하지 않았습니다
Matthieu Napoli

입력 스트림에 줄 바꿈이 없을 수 있습니까? 그렇다면 grep이 진행되지 않습니다.
Lynch

답변:


1326

grepBSD grep (FreeBSD, Mac OS X 등)을 사용할 때의 라인 버퍼링 모드를 켜십시오

tail -f file | grep --line-buffered my_pattern

기본적으로 플러시되므로 GNU grep (거의 모든 Linux에서 사용)에 대해서는이 작업을 수행 할 필요가 없습니다 (SmartOS, AIX 또는 QNX와 같은 다른 유닉스 계열의 경우 YMMV).


3
@MichaelNiemand 당신은 꼬리 -F 파일을 사용할 수 있습니다 | grep --line-buffered my_pattern
jcfrei

47
@MichaelGoldshteyn 진정하세요. 사람들은 구글이 "grep line buffered"를 할 때이 페이지를 발견하고 그것을 질문으로 제기 된 것이 아닐 수도있는 문제를 해결하기 때문에 그것을 찬성했습니다.
raine

4
의 출력을 grep하려고 여기 왔습니다 strace. 이 없으면 --line-buffered작동하지 않습니다.
sjas

5
@MichaelGoldshteyn (그의 주석의 upvoters가) : 난 항상 이것에 문제가 있었다 tail -f | grep, 그리고 --line-buffered그것은 나를 해결합니다 (우분투 14.04에를, GNU 그렙 버전 2.16). "stdout이 tty 인 경우 라인 버퍼링 사용"논리는 어디에 구현되어 있습니까? 에서 git.savannah.gnu.org/cgit/grep.git/tree/src/grep.c , line_buffered만 인수 파서에 의해 설정된다.
Aasmund Eldhuset

8
@MichaelGoldshteyn BSD grep을 사용하는 macOS에 --line-buffered있고 출력이 없습니다. 그러나 테스트 후 GNU grep이 설명하는 것처럼 보입니다. 따라서 대부분의 유닉스와 마찬가지로 플랫폼의 구현에 달려 있습니다. 문제는 플랫폼을 지정하지 않았기 때문에, 당신의 정보를 허위로 표시 - BSD 그렙에 대한 코드를 검토하고 GNU 그렙과 비교 한 후, 동작은 확실히 --line 버퍼 옵션에 의해 제어됩니다. GNU grep 만 기본적으로 플러시됩니다.
Richard Waite

118

나는 tail -f <file> | grep <pattern> 항상 .

grep이 끝날 때까지 기다리지 않고 기다릴 것입니다 (우분투를 사용하고 있습니다).


4
꽤 오래 지속될 수 있으므로 참을성이 없도록하십시오.
glglgl

대략 시간이 얼마나 걸립니까?
Matthieu Napoli

@Matthieu : 주로 grep 대상과 OS에있는 버퍼 크기에 따라 다릅니다. grep이 몇 시간마다 짧은 줄에만 일치하면 첫 번째 플러시 전에 며칠이 걸립니다.
tripleee

13
Tail은 출력 버퍼링을 사용하지 않습니다. grep은 사용합니다.
XzKto

7
아니요, grep은 출력이 tty 장치로 갈 때 출력 응답을 명확하게 수행하므로 출력 버퍼링을 수행하지 않습니다. 라인 버퍼링을 수행합니다! 정답이며 허용되는 답변이어야합니다. 자세한 내용은 현재 허용 된 ( 잘못된 ) 답변에 대한 더 긴 의견을 참조하십시오.
Michael Goldshteyn

67

문제는 grep이 일부 출력 버퍼링을 사용한다는 것입니다. 시험

tail -f file | stdbuf -o0 grep my_pattern

grep의 출력 버퍼링 모드를 unbuffered로 설정합니다.


7
그리고 이것은 많은 다른 명령에 사용될 수있는 장점이 있습니다 grep.
피터 V. Mørch

4
그러나 내가 더 많이 연주 한 후에 발견 한 것처럼 일부 명령은 tty에 연결되었을 때만 출력을 플러시하며 unbuffer( expect-devdebian 의 패키지에 있음) king 입니다. 그래서 stdbuf보다 unbuffer를 사용합니다.
Peter V. Mørch

5
@Peter V. Mørch 네, 맞습니다. 언 버퍼는 때때로 stdbuf가 할 수없는 곳에서 작동 할 수 있습니다. 그러나 문제를 이해하는 대신 항상 문제를 해결하는 '매직'프로그램을 찾으려고 생각합니다. 가상 tty 생성은 관련이없는 작업입니다. Stdbuf는 우리가 원하는 것을 정확하게 수행하고 (표준 출력 버퍼가 값을 제공하도록 설정) unbuffer는 원하지 않는 많은 숨겨진 것들을 수행합니다 ( topstdbuf 및 unbuffer와 대화식 비교 ). 그리고 '매직'솔루션은 없습니다. 언 버퍼는 때때로 실패합니다. 예를 들어 awk는 다른 버퍼 구현을 사용합니다 (stdbuf도 실패합니다).
XzKto

2
"하지만 문제를 이해하는 대신 항상 문제를 해결하는 '매직'프로그램을 찾으려고 생각합니다." - 내 생각 엔 당신이 맞다! ;-)
Peter V. Mørch

1
pixelbeat.org/programming/stdio_bufferingstdbuf 에서`unbuffer, stdio buffering에 대한 더 많은 정보
Tor Klingberg

13

꼬리가 아닌 전체 파일 에서 일치 항목을 찾고 새 일치 항목을 기다리고 기다리려면 다음과 같이하십시오.

tail -c +0 -f <file> | grep --line-buffered <pattern>

-c +0플래그는 출력을 시작해야 함을 말한다 0바이트 ( -c시작 (에서) +파일을).


12

대부분의 경우, 가능 tail -f /var/log/some.log |grep foo하며 제대로 작동합니다.

실행중인 로그 파일에 여러 그렙을 사용해야하고 출력이없는 것을 발견하면 다음과 같이 --line-buffered스위치를 중간 그렙 에 붙여야합니다 .

tail -f /var/log/some.log | grep --line-buffered foo | grep bar

7

당신은이 답변을 향상으로 생각할 수 있습니다 .. 보통 나는 사용하고 있습니다

tail -F <fileName> | grep --line-buffered  <pattern> -A 3 -B 5

파일 회전의 경우 -F가 더 좋습니다 (파일이 회전하면 -f가 제대로 작동하지 않음)

-A와 -B는 패턴 발생 직전과 직후에 라인을 얻는 데 유용합니다.이 블록은 점선 구분 기호 사이에 나타납니다.

하지만 저에게는 다음을 선호합니다

tail -F <file> | less

스트리밍 로그 내부를 검색하려는 경우 매우 유용합니다. 앞뒤로 깊게 쳐다 봐


4
grep -C 3 <pattern>N이 같으면 -A <N> 및 -B <N>을 대체합니다.
AKS

6

아무도 내 평소 이동을 제공하는 것을 보지 못했습니다.

less +F <file>
ctrl + c
/<search term>
<enter>
shift + f

ctrl + c언제든지 파일을 중지하고 탐색 하는 데 사용할 수 shift + f있으며 실시간 스트리밍 검색으로 돌아 가기 위해 사용할 수 있기 때문에 이것을 선호합니다 .


4

sed 가 더 나은 선택이 될 것입니다 ( 스트림 편집기)

tail -n0 -f <file> | sed -n '/search string/p'

그런 다음 특정 문자열을 찾은 후 tail 명령을 끝내려면 다음을 수행하십시오.

tail --pid=$(($BASHPID+1)) -n0 -f <file> | sed -n '/search string/{p; q}'

분명히 bashism : $ BASHPID는 tail 명령의 프로세스 ID입니다. sed 명령은 파이프에서 꼬리 다음에옵니다. 따라서 sed 프로세스 ID는 $ BASHPID + 1입니다.


1
시스템에서 다음 프로세스가 시작되었다는 가정 ( $BASHPID+1)은 많은 상황에서 잘못된 것이며, 이는 OP가 요청한 버퍼링 문제를 해결하는 데 아무런 도움이되지 않습니다. 특히, 여기서 추천 sed하는 grep것은 단지 (의심스러운) 선호의 문제처럼 보입니다. ( 이것이 당신이 전달하려는 시점이라면 p;q행동을 얻을 수 있습니다 grep -m 1.)
tripleee

작동, sed 명령은 grep 명령이 준비 --line-buffered되지 않은 준비가 되 자마자 각 줄을 인쇄합니다 . 나는 마이너스 1을 진지하게 이해하지 못한다.
MUY Belgium

지금까지 버퍼링은 grep 의 문제라는 것이 밝혀 졌습니다. sed를 사용하여 라인 버퍼링을 처리하기 위해 특별한 조치가 필요하지 않습니다. 기본 동작이므로 단어 스트림에 중점을 둡니다 . 그리고 사실, $ BASHPID + 1이 올바른 pid 를 따를 것이라는 보장 은 없지만 pid 할당 이 순차적 이고 파이프 명령에 pid가 즉시 할당 되므로 완전히 가능성이 있습니다.
Christian Herr

1

예, 이것은 실제로 잘 작동합니다. Grep대부분의 유닉스 명령어는 한 번에 한 줄씩 스트림에서 작동합니다. 꼬리에서 나오는 각 줄은 분석되고 일치하면 전달됩니다.


2
실제로는 정확하지 않습니다. grep파이프 체인의 마지막 명령 인 경우 설명대로 작동합니다. 그러나 중간에 있으면 한 번에 약 8k 출력을 버퍼링합니다.
Mahmoud Al-Qudsi

1

이 명령은 나를 위해 일합니다 (수세) :

mail-srv:/var/log # tail -f /var/log/mail.info |grep --line-buffered LOGIN  >> logins_to_mail

메일 서비스에 대한 로그인 수집


-1

당신은 확실히 성공하지 못할 것입니다

tail -f /var/log/foo.log |grep --line-buffered string2search

꼬리의 별칭으로 "colortail"을 사용하는 경우 (예 : bash에서

alias tail='colortail -n 30'

tail isan alias of와 같은 것을 출력하면 type alias로 확인할 수 있습니다. colortail -n 30 . 그럼 당신은 범인이 있습니다 :)

해결책:

로 별칭을 제거

unalias tail

이 명령으로 '실제'꼬리 이진을 사용하고 있는지 확인하십시오.

type tail

다음과 같이 출력되어야합니다 :

tail is /usr/bin/tail

그런 다음 명령을 실행할 수 있습니다

tail -f foo.log |grep --line-buffered something

행운을 빕니다.


-4

라인 버퍼 옵션이없는 grep 대신 awk (또 다른 훌륭한 bash 유틸리티)를 사용하십시오! 꼬리에서 데이터를 지속적으로 스트리밍합니다.

이것은 당신이 grep을 사용하는 방법입니다

tail -f <file> | grep pattern

이것은 당신이 awk를 사용하는 방법입니다

tail -f <file> | awk '/pattern/{print $0}'

6
이것은 정확하지 않습니다. 기본적으로 다른 표준 유닉스 도구와 마찬가지로 라인 버퍼링을 수행합니다. (또한 {print $0}조건이
지날
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.