매우 간단한 검색을 수행했습니다.

grep -R Milledgeville ~/Documents 

그리고 잠시 후이 오류가 나타납니다.

grep: memory exhausted 

어떻게 피할 수 있습니까?

시스템에 10GB의 RAM이 있고 응용 프로그램이 거의 없습니다. 실행 중이므로 간단한 grep이 메모리가 부족하다는 사실에 정말 놀랐습니다. ~/Documents는 약 100GB이며 모든 종류의 파일을 포함합니다.

grep -RI에는이 문제가 없을 수도 있지만 원합니다. 바이너리 파일에서도 검색 할 수 있습니다.

답변

두 가지 잠재적 인 문제 :

  • grep -R (OS / X 10.8 이상에있는 수정 된 GNU grep 제외)는 심볼릭 링크를 따릅니다. ~/Documents에 100GB의 파일이 있습니다. 예를 들어 /에 대한 심볼릭 링크가 여전히있을 수 있으며 다음을 포함한 전체 파일 시스템을 검색하게됩니다. /dev/zero와 같은 파일. 최신 GNU grep와 함께 grep -r를 사용하거나 표준 구문을 사용합니다.

    find ~/Documents -type f -exec grep Milledgeville /dev/null {} + 

    (단, 종료 상태는 패턴이 일치하는지 여부를 반영하지 않습니다.)

  • grep는 패턴과 일치하는 줄을 찾습니다.이를 위해 메모리에 한 번에 한 줄씩로드해야합니다. 다른 많은 iv id = “cc67858b36″과 달리 GNU grep >

구현은 읽는 행의 크기에 제한이 없으며 바이너리 파일에서 검색을 지원합니다. 따라서 사용 가능한 메모리보다 큰 줄이 매우 큰 (즉, 두 개의 줄 바꿈 문자가 매우 멀리있는) 파일이 있으면 실패합니다.

이것은 일반적으로 a에서 발생합니다. 희소 파일입니다. 다음과 같이 재현 할 수 있습니다.

truncate -s200G some-file grep foo some-file 

그건 해결하기 어렵습니다. 다음과 같이 할 수 있습니다 (여전히 GNU grep) :

find ~/Documents -type f -exec sh -c "for i do tr -s "\0" "\n" < "$i" | grep --label="$i" -He "$0" done" Milledgeville {} + 

입력을 . 문제가 스파 스 파일로 인한 경우에 적용됩니다.

대용량 파일에 대해서만 수행하여 최적화 할 수 있습니다.

find ~/Documents -type f \( -size -100M -exec \ grep -He Milledgeville {} + -o -exec sh -c "for i do tr -s "\0" "\n" < "$i" | grep --label="$i" -He "$0" done" Milledgeville {} + \) 

파일이 스파 스가 아니고 iv id =”14dfe9e720 “이전의 GNU 버전 grep이있는 경우 >

, --mmap 옵션을 사용할 수 있습니다. 라인이 복사되는 것과 반대로 메모리에 mmapped되므로 시스템이 항상 메모리를 회수 할 수 있습니다. y 페이지를 파일로 페이징합니다. 이 옵션은 GNU grep 2.6

댓글

  • 에서 제거되었습니다. @GodricSeer, 여전히 파일의 많은 부분을 단일 버퍼로 읽을 수 있지만 ' 그 안에서 문자열을 찾지 못하고 ' 개행 문자도 발견하지 못했습니다. 일치하는 항목이 발견되면 표시해야하므로 해당 단일 버퍼를 메모리에 유지하고 다음 버퍼를 읽습니다. 따라서 문제는 여전히 동일합니다. 실제로 200GB 스파 스 파일의 grep은 OOM에서 실패합니다.
  • @GodricSeer, 아닙니다. 줄이 모두 작은 경우 grep는 지금까지 처리 한 버퍼를 삭제할 수 있습니다. 몇 킬로바이트 이상의 메모리를 사용하지 않고도 grep yes의 출력을 무기한으로 사용할 수 있습니다. 문제는 라인의 크기 입니다.
  • GNU grep --null-data 옵션도 여기에서 유용 할 수 있습니다. 줄 바꿈 대신 NUL을 입력 줄 종결 자로 강제 사용합니다.
  • @ 1_CR, 좋은 점이지만 출력 줄 종결자를 NUL로 설정합니다.
  • fold 명령이 도움이됩니까? 예를 들어 필요한 메모리 양을 4GB로 제한하려면 dd if=/dev/sda | fold -b $((4096*1024*1024)) | grep -a "some string" 를 생각해보세요.

Answer

저는 보통

find ~/Documents | xargs grep -ne "expression" 

여러 가지 방법을 시도해 보았는데 이것이 가장 빠른 것으로 나타났습니다. 이것은 파일 이름에 공백이있는 파일을 잘 처리하지 못합니다.이 경우를 알고 있고 grep의 GNU 버전이있는 경우 다음을 사용할 수 있습니다.

find ~/Documents -print0 | xargs -0 grep -ne "expression" 

사용할 수없는 경우 :

 find ~/Documents -exec grep -ne "expression" "{}" \; 

모든 파일에 대해 grep을 exec 사용할 수 있습니다.

댓글

  • 공백이있는 파일에서 중단됩니다.
  • 음, 맞습니다.
  • find -print0 | xargs -0 grep -ne 'expression'
  • @ChrisDown을 사용하면 고장난 휴대용 솔루션이 아니라 비확산적인 솔루션입니다.
  • @ChrisDown Most 주요 유니스는 지금까지 find -print0xargs -0를 채택했습니다 : 세 가지 BSD, MINIX 3, Solaris 11,…

답변

이 문제를 해결할 수있는 몇 가지 방법을 생각할 수 있습니다.

  • 대신 한 번에 모든 파일을 검색하려면 한 번에 하나의 파일을 수행하십시오.예 :

    find /Documents -type f -exec grep -H Milledgeville "{}" \; 
  • 단어가 포함 된 파일 만 알고 싶다면 grep -l 대신. grep은 첫 번째 히트 이후 검색을 중단하므로 “대용량 파일을 계속 읽을 필요가 없습니다.

  • 실제 텍스트도 원한다면 문자열 2 개를 사용할 수 있습니다. 별도의 그립 :

    for file in $( grep -Rl Milledgeville /Documents ); do grep -H Milledgeville "$file"; done 

댓글

  • 마지막 예 유효한 구문이 아닙니다. ' 명령 대체를 수행해야합니다 ('이를 수행해서는 안됩니다. grep는 파일 이름에 유효한 구분 기호를 사용하여 출력합니다. 또한 $file를 인용해야합니다.
  • 후자의 예는 문제가 있습니다. 파일 이름에 줄 바꿈이나 공백이있는 문제가있는 경우 (for가 파일을 두 개의 인수로 처리하게됩니다.)
  • @DravSloan 편집, 개선, 여전히 법적 파일 이름에 문제가 있습니다.
  • 네 답변의 일부 였기 때문에 그대로 두었습니다. 실행되도록 개선하려고했습니다. s 파일에 공백 / 줄 바꿈 등이 없음).
  • 그의 수정-> 그녀, 사과드립니다 Jenny : /

답변

손실 된 데이터를 검색하기 위해 6TB 디스크를 찾고 있는데 메모리 소모 오류가 발생했습니다. 이것은 다른 파일에서도 작동합니다.

우리가 생각 해낸 해결책은 dd를 사용하여 디스크를 청크 단위로 읽고 청크를 그레 핑하는 것입니다. 다음은 코드 (big-grep.sh)입니다.

#problem: grep gives "memory exhausted" error on 6TB disks #solution: read it on parts if [ -z $2 ] || ! [ -e $1 ]; then echo "$0 file string|less -S # greps in chunks"; exit; fi FILE="$1" MATCH="$2" SIZE=`ls -l $1|cut -d\ -f5` CHUNKSIZE=$(( 1024 * 1024 * 1 )) CHUNKS=100 # greps in (100 + 1) x 1MB = 101MB chunks COUNT=$(( $SIZE / $CHUNKSIZE * CHUNKS )) for I in `seq 0 $COUNT`; do dd bs=$CHUNKSIZE skip=$(($I*$CHUNKS)) count=$(( $CHUNKS+1)) if=$FILE status=none|grep -UF -a --context 6 "$MATCH" done 

댓글

  • 읽지 않은 경우 청크가 겹치면 청크 경계에서 일치를 놓칠 수 있습니다. 겹치는 부분은 최소한 일치 할 것으로 예상되는 문자열만큼 커야합니다.
  • 각 100MB 청크에서 추가로 1MB를 검색하도록 업데이트되었습니다. 저렴한 해킹

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다