非常に単純な検索を行っていました:

grep -R Milledgeville ~/Documents 

そしてしばらくすると、このエラーが表示されました:

grep: memory exhausted 

これを回避するにはどうすればよいですか?

システムに10GBのRAMがあり、アプリケーションがほとんどありません実行中なので、単純なgrepのメモリが不足していることに本当に驚いています。 ~/Documentsは約100GBで、あらゆる種類のファイルが含まれています。

grep -RIにはこの問題はないかもしれませんが、必要です。バイナリファイルも検索します。

回答

2つの潜在的な問題:

  • grep -R(OS / X10.8以降で見つかった変更されたGNU grepを除く)はシンボリックリンクをたどるので、 ~/Documentsに100GBのファイルがある場合、たとえば/へのシンボリックリンクが残っている可能性があり、ファイルシステム全体をスキャンすることになります。 /dev/zeroのようなファイル。 grep -rを新しいGNU grepで使用するか、標準の構文を使用します:

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

    (ただし、終了ステータスはパターンが一致するかどうかを反映しないことに注意してください)。

  • grepは、パターンに一致する行を検索します。そのためには、メモリに一度に1行ずつロードする必要があります。他の多くのiv id = “cc67858b36″とは対照的に、GNU grep >

の実装では、読み取る行のサイズに制限はなく、バイナリファイルでの検索をサポートします。したがって、使用可能なメモリよりも大きい非常に大きな行(つまり、2つの改行文字が非常に遠い)のファイルがある場合、失敗します。

これは通常、スパースファイル。次のコマンドで再現できます:

truncate -s200G some-file grep foo some-file 

これは回避が困難です。(GNU ):

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オプションを使用できます。行はメモリにコピーされるのではなく、メモリにマッピングされます。つまり、システムはいつでもメモリを再利用できます。 yページをファイルにページアウトします。このオプションはGNU grep 2.6

コメント

  • で削除されました@GodricSeerの場合でも、ファイルの大部分を単一のバッファに読み込むことができますが、'そこに文字列が見つからず、'改行文字も見つかりませんでした。一致するものが見つかった場合に表示する必要があるため、その単一のバッファをメモリに保持し、次のバッファを読み込みます。したがって、問題は同じです。実際には、200GBのスパースファイルのgrepはOOMで失敗します。
  • @GodricSeer。行がすべて小さい場合、grepはこれまでに処理したバッファを破棄できます。 grep yesの出力は、数キロバイトを超えるメモリを使用せずに無期限に実行できます。問題は行のサイズです
  • GNU grep --null-dataオプションもここで役立つ場合があります。入力行ターミネーターとして改行の代わりにNULを強制的に使用します。
  • @ 1_CR、良い点ですが、出力行ターミネーターもNULに設定されます。
  • fold コマンドはそのような状況で役立ちますか?たとえば、dd if=/dev/sda | fold -b $((4096*1024*1024)) | grep -a "some string" を考えて必要なメモリ量を4GBに制限します

回答

私は通常そうします

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を採用しています。3つすべてのBSD、MINIX 3、Solaris 11、…

回答

これを回避する方法はいくつか考えられます:

  • 代わりにすべてのファイルを一度にgrepする場合は、一度に1つのファイルを実行します。例:

    find /Documents -type f -exec grep -H Milledgeville "{}" \; 
  • 単語が含まれているファイルのみを知る必要がある場合は、grep -l。 grepは最初のヒット後に検索を停止するため、「巨大なファイルを読み続ける必要はありません

  • 実際のテキストも必要な場合は、2つ文字列にすることができます個別のgrepに沿って:

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

コメント

  • 最後の例は有効な構文ではありません-'コマンド置換を実行する必要があります('は、'を実行しないでください。 = “cc67858b36″>

は、ファイル名で有効な区切り文字を使用して出力します。また、$fileを引用する必要があります。

  • 後者の例では問題が発生します。ファイル名にnewlineまたはwhitespaceが含まれている問題があります(これにより、forがファイルを2つの引数として処理します)
  • @DravSloan編集中改善されましたが、まだ正当なファイル名が壊れています。
  • ええ、それは彼女の答えの一部だったので、そのままにしておきました。実行されるように改善しようとしました( sファイルにスペース/改行などはありません。
  • 彼の訂正->彼女、謝罪ジェニー:/
  • 回答

    6TBのディスクをgrepして失われたデータを検索し、メモリが使い果たされました-エラー。これは他のファイルでも機能するはずです。

    私たちが思いついた解決策は、ddを使用してディスクをチャンクで読み取り、チャンクをgrepすることでした。これはコード(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余分に検索するように更新されました…安価なハック

    コメントを残す

    メールアドレスが公開されることはありません。 * が付いている欄は必須項目です