while 루프가 작동하지 않는 "tail -f | grep error"

while 루프가 작동하지 않는 "tail -f | grep error"

다음 명령은 결과를 제공하지 않았습니다. grep파일에서 오류 행을 추출하여 테이블에 삽입하고 싶습니다 .

작동하지 않는 명령:

tail -f logfile.log | grep  ERROR|while read msg; do psql -d testdb -c insert into t values('$msg'); done

그러나 grep ERROR명령에서 코드를 제거하면 예상대로 작동합니다. 무슨 일이 일어났는지 모르겠어요?

잘 작동하는 명령:

tail -f logfile.log|while read msg; do psql -d testdb -c insert into t values('$msg'); done

파일에 다음 데이터가 있다고 가정할 수 있습니다.

ERROR
sql committed
ERROR
ERROR
error
...

답변1

두가지:

  1. 질문에 작성된 것처럼 $msg작은따옴표를 사용했기 때문에 코드는 리터럴 문자열(유효한 경우)을 삽입합니다. 대신 큰따옴표를 사용하세요. 여기에서는 전체 문장을 큰따옴표로 묶었습니다. 그러면 내부가 확장됩니다 $msg. 셸 코드는 여전히 취약합니다 . 이상적으로는 단일 또는 기타 특수 문자로 인해 명령문이 손상되지 않도록(또는 더 나쁜 경우 참조) grep문자열을 적절하게 삭제해야 합니다.$msg'사용자의 의견카스다음과 같은).

    tail -f logfile.log |
    grep -F 'ERROR' |
    while read msg; do
        psql -d testdb -c "insert into t values('$msg')"
    done
    

    또한 고정 문자열을 사용하여 검색할 때 호출을 추가했습니다 -F(주로 문서화 목적입니다).grep

  2. grep출력 버퍼가 가득 찰 때까지 아무것도 생성되지 않도록 출력을 버퍼링합니다. 이는 실제로는 "작동하지 않는다"는 인상을 주지만 grep출력 버퍼를 플러시할 때까지는 아무 작업도 수행하지 않습니다. 이는 충분한 데이터가 있을 때 수행됩니다. 이는 성능 최적화입니다.

    GNU grep(및 OpenBSD와 같은 동일한 유틸리티의 다른 구현)는 --line-buffered해당 옵션을 통해 라인 버퍼링을 수행할 수 있습니다.

    tail -f logfile.log |
    grep --line-buffered -F 'ERROR' |
    while read msg; do
        psql -d testdb -c "insert into t values('$msg')"
    done
    

참고: 현재 PostgreSQL(?) 인스턴스가 실행되고 있지 않기 때문에 아직 테스트하지 않았습니다.

관련 정보