web-dev-qa-db-ja.com

文字列のすべてのファイルを「grep」するのに時間がかかる

grepコマンドオプション

ドライブ全体で文字列を検索したかった。 Stack Overflow で受け入れられた回答に従ってください:

Sudo time grep -rnw '/' -e 'Sony 50"'

そして、最速のPCIe NVMe M.2 SSDの1つで20 GBのデータを処理するのに53時間かかりました。 Samsung Pro 960。

grep出力ログ

grepがいくつかのファイルを処理すると、エラーメッセージが生成されます。これらは、コマンドに2>/dev/nullを追加することで抑制できます。ただし、エラーは進行中のフィードバックを提供します。サンプル出力の一部(すべてが適合するわけではありません)は以下のとおりです。

Binary file /home/Me/.config/google-chrome/Default/Sync Data/SyncData.sqlite3 matches
grep: /sys/kernel/security/ima/policy: Permission denied
grep: /sys/kernel/slab/:dt-0000008/alloc_calls: Function not implemented
grep: /sys/kernel/slab/:dt-0000008/free_calls: Function not implemented
      (... SNIP ... 12 hours later PID 882 processed below...)
grep: /proc/882/task/922/attr/sockcreate: Invalid argument
grep: /proc/882/task/923/mem: Input/output error
      (... SNIP ... 24 hours later PID 2954 below...)
grep: /proc/2598/attr/sockcreate: Invalid argument
grep: /proc/2954/task/2954/mem: Input/output error
      (... SNIP ... 42 hours later PID 4396 below...)
grep: /proc/4389/attr/sockcreate: Invalid argument
grep: /proc/4396/task/4396/mem: Input/output error
      (... SNIP ... After 53 hours `grep` finally finishes...)
grep: /run/user/1000/gvfs: Permission denied
Command exited with non-zero status 2
97355.34user 83223.12system 53:07:40elapsed 94%CPU (0avgtext+0avgdata 31116maxresident)k
593910020inputs+0outputs (1major+10731minor)pagefaults 0swaps

grepはフリーズした印象を与えます

画面が1時間更新されず、ハードディスクのライトがあまり点滅しないため、grepがフリーズしたと時々思った。しかし、Conkyは、それがまだ実行中であり、単一のコアで100%CPUを使用していると言います このGIFで見られるように

Linux(Ubuntu 16.04.3 LTS)パーティションで使用されている43.8 GiB_のうち19.5 GiBのうち、このスペースの半分、10 GBはカーネルによって使用されます。カーネルのダウンロードとテストは私のパスタイムです。


このテストは、週末と月曜日のほとんどを完了するのにかかりました。

grepを高速化し、それでも探しているものを取得するにはどうすればよいですか?

7

仮想ファイルシステムを除外する

サンプル出力ログを見ると、仮想ファイルシステムが検索に含まれていることがわかりますが、これは時間の無駄です。 --exclude-dirオプションを使用して、これらのディレクトリおよびその他のディレクトリを検索から削除します。例えば:

Sudo time grep -rnw --exclude-dir={boot,dev,lib,media,mnt,proc,root,run,sys,/tmp,tmpfs,var} '/' -e 'Sony 50"'

grep/procディレクトリチェーンを解析するとき、すべてのプロセスIDを無駄に調べているため、私の場合は1日以上かかります。

また、/mntを処理するとき、マウントされたWindows NTFSドライブとUSBを不必要に調べます。

/mediaは、CD/DVDドライブと外部USBドライブを保持します。

出力:

$ Sudo time grep -rnw --exclude-dir={boot,dev,lib,media,mnt,proc,root,run,sys,/tmp,tmpfs,var} '/' -e 'Sony 50"'
Binary file /home/Me/.config/google-chrome/Default/Sync Data/SyncData.sqlite3 matches
11.35user 13.83system 0:56.35elapsed 44%CPU (0avgtext+0avgdata 8480maxresident)k
17369032inputs+0outputs (0major+1620minor)pagefaults 0swaps

そこに行く56秒の代わりに50時間

usr(私の場合は6.5 GBのファイルを含む)を検索から除外すると、わずか8秒です。

4.48user 1.80system 0:08.75elapsed 71%CPU (0avgtext+0avgdata 6012maxresident)k
13008964inputs+0outputs (0major+1180minor)pagefaults 0swaps

興味深いメモ

システムディレクトリを除外することで、grepを追跡しやすくなり、シングルコアでCPUが100%に達することはありません。さらに、ハードディスクのライトが常に点滅するので、grepが実際に機能していて、「輪になって考えている」のではないことがわかります。

tmpの前に/を付けない場合、/home/Me/tmpなどのtmpを含むサブディレクトリは無視されます。 --exclude-dir /tmpを使用すると、ディレクトリ/home/Me/tmpが検索されます。

一方、sysの前に/を付けると、/sysディレクトリが検索され、エラーが報告されます。 /procについても同様です。そのため、sys,procを使用し、/をプレフィックスとして使用しないでください。同じことが、私がテストした他のシステムディレクトリにも当てはまります。

エイリアスを作成grepall

~/.bashrcにエイリアスを設定することを検討してください。そうすると、毎回--exclude-dirパラメーターリストを入力する必要がなくなります。

alias grepall="grep --exclude-dir={boot,dev,lib,media,mnt,proc,root,run,sys,/tmp,tmpfs,var}"

詳細な時間内訳

このセクションでは、--exclude-dirパラメータリストにディレクトリを増分的に追加することで、どれだけの時間を節約できるかを説明します。

  • /procおよび/sys保存52時間
  • /media保存
  • /mnt保存21分
  • /usr/srcsrcを指定)保存53秒
  • /lib/modulesmodulesを指定)保存9秒

/procおよび/sysディレクトリを除外する

/procおよび/sysディレクトリは最も時間がかかり、ほとんどのエラーを検索して生成するのに最も役に立ちません。これらの2つのディレクトリは実行時に動的に作成され、grepにしたい永続的なファイルが含まれていないため、 "役に立たない"です。

それらを除外することで、大幅な時間の節約が実現します。

$ Sudo time grep -rnw --exclude-dir={proc,sys} '/' -e 'Garbage 098jfsd'
/var/log/auth.log:4653:Feb 16 17:46:20 alien Sudo:     rick : TTY=pts/18 ; PWD=/home/rick/Downloads ; USER=root ; COMMAND=/usr/bin/time grep -rnw --exclude-dir=proc --exclude-dir=sys / -e Garbage 098jfsd
Binary file /var/log/journal/d7b25a27fe064cadb75a2f2f6ca7764e/system.journal matches
grep: /media/rick/S3A6550D005/hiberfil.sys: Input/output error
      (... SNIP ...)
grep: /media/rick/S3A6550D005/winproductkey: Input/output error
grep: /run/user/1000/gvfs: Permission denied
Command exited with non-zero status 2
422.43user 112.91system 26:59.03elapsed 33%CPU (0avgtext+0avgdata 31152maxresident)k
379671064inputs+0outputs (1major+10738minor)pagefaults 0swaps

のみ27分この時間を節約52時間

ただし、まだエラーがあります。 /varディレクトリ。実行時に作成される「仮想ディレクトリ」でもあります。 Android携帯電話を含む/runディレクトリと、USB外付けHDDエンクロージャーに接続された古い壊れたラップトップハードドライブを含む/mediaディレクトリ。

除外リストに/mediaを追加

/mediaディレクトリには、USB 3.0ポート経由で接続された古いラップトップドライブが含まれています。 Smartctlは、ドライブ上のエラーを毎日報告しますが、探しているファイルはありません。時間を節約し、エラーメッセージを減らすために除外します。

$ Sudo time grep -rnw --exclude-dir={proc,sys,media} '/' -e 'Garbage 654asdf'
/var/log/auth.log:4664:Feb 16 18:26:27 alien Sudo:     rick : TTY=pts/18 ; PWD=/home/rick/Downloads ; USER=root ; COMMAND=/usr/bin/time grep -rnw --exclude-dir=proc --exclude-dir=sys --exclude-dir=media / -e Garbage 654asdf
Binary file /var/log/journal/d7b25a27fe064cadb75a2f2f6ca7764e/system.journal matches
grep: /run/user/1000/gvfs: Permission denied
Command exited with non-zero status 2
405.51user 105.38system 23:26.89elapsed 36%CPU (0avgtext+0avgdata 30908maxresident)k
365800875inputs+0outputs (0major+10961minor)pagefaults 0swaps

USB 3.0エンクロージャを介して接続された障害のあるハードドライブを除外すると、3分しか節約できませんでしたが、エラーメッセージは減少しました。

除外リストに/mnt(Windows NTFSパーティション)を追加します

/mntディレクトリには次が含まれます。

  • 105 GiBのデータがあるSSD上の2つのNTFS Windows 10パーティション(C:およびE:
  • 42 GiB_のデータを持つHDD上の1つのNTFS Windows 10パーティション(D:

Windowsには関心がないため、時間を節約するために/mntを除外します。

$ ll /mnt
total 44
drwxr-xr-x  5 root root  4096 Nov 12 07:19 ./
drwxr-xr-x 27 root root  4096 Feb 15 20:43 ../
drwxrwxrwx  1 root root  8192 Dec 30 14:00 c/
drwxrwxrwx  1 root root  8192 Dec 30 14:31 d/
drwxrwxrwx  1 root root 20480 Jan  1 13:22 e/

$ Sudo time grep -rnw --exclude-dir={proc,sys,media,mnt} '/' -e 'Garbage zx5cv7er'
/var/log/auth.log:5093:Feb 17 10:31:44 alien Sudo:     rick : TTY=pts/18 ; PWD=/home/rick/Downloads ; USER=root ; COMMAND=/usr/bin/time grep -rnw --exclude-dir=proc --exclude-dir=sys --exclude-dir=media --exclude-dir=mnt / -e Garbage zx5cv7er
Binary file /var/log/journal/d7b25a27fe064cadb75a2f2f6ca7764e/system.journal matches
grep: /run/user/1000/gvfs: Permission denied
Command exited with non-zero status 2
51.50user 23.28system 2:08.85elapsed 58%CPU (0avgtext+0avgdata 15800maxresident)k
39866258inputs+0outputs (0major+6059minor)pagefaults 0swaps

grepは2分8秒しかかかりません。 147 Gibのプログラムとデータを含むWindows 10パーティションを除外することで21.5分節約!

除外リストに/usr/src Linuxヘッダーを追加

/usr/srcディレクトリには、Linuxヘッダーのソースコードが含まれています。私の場合、20以上のカーネルが手動でインストールされており、かなりのスペースが必要です。使用される引数がsrcであるにもかかわらずディレクトリを指定するには:

$ du -h -s /usr/src
3.2G    /usr/src

$ Sudo time grep -rnw --exclude-dir={proc,sys,media,mnt,src} '/' -e 'Garbage z5cv7er'
/var/log/auth.log:5096:Feb 17 10:34:28 alien Sudo:     rick : TTY=pts/18 ; PWD=/home/rick/Downloads ; USER=root ; COMMAND=/usr/bin/time grep -rnw --exclude-dir=proc --exclude-dir=sys --exclude-dir=media --exclude-dir=mnt --exclude-dir=src / -e Garbage z5cv7er
Binary file /var/log/journal/d7b25a27fe064cadb75a2f2f6ca7764e/system.journal matches
grep: /run/user/1000/gvfs: Permission denied
Command exited with non-zero status 2
44.21user 8.54system 1:15.51elapsed 69%CPU (0avgtext+0avgdata 15864maxresident)k
33754180inputs+0outputs (0major+6062minor)pagefaults 0swaps

これで、grepは1分15秒しかかかりません。 /usr/srcリストでsrcを指定して--exclude-dirを除外すると、53秒節約できます。

除外リストに/lib/modulesカーネルモジュールを追加

/lib/modulesディレクトリには、コンパイルされたカーネルモジュールが含まれています。使用される引数がmodulesであるにもかかわらずディレクトリを指定するには:

$ du -h -d1 /lib/modules
285M    /lib/modules/4.14.18-041418-generic
282M    /lib/modules/4.14.14-041414-generic
     (... SNIP ...)
228M    /lib/modules/4.9.76-040976-generic
6.0G    /lib/modules

$ Sudo time grep -rnw --exclude-dir={proc,sys,media,mnt,src,modules} '/' -e 'Garbage 1cv7fer'
/var/log/auth.log:5117:Feb 17 11:07:41 alien Sudo:     rick : TTY=pts/18 ; PWD=/home/rick/Downloads ; USER=root ; COMMAND=/usr/bin/time grep -rnw --exclude-dir=proc --exclude-dir=sys --exclude-dir=media --exclude-dir=mnt --exclude-dir=src --exclude-dir=modules / -e Garbage 1cv7fer
Binary file /var/log/journal/d7b25a27fe064cadb75a2f2f6ca7764e/system.journal matches
grep: /run/user/1000/gvfs: Permission denied
Command exited with non-zero status 2
19.22user 5.84system 0:35.61elapsed 70%CPU (0avgtext+0avgdata 15600maxresident)k
22111388inputs+0outputs (0major+6059minor)pagefaults 0swaps

6 GBのカーネルモジュールをスキップすると、grep時間は36秒になります。 /lib/modulesパラメーターにmodulesを指定して--exclude-dirを追加すると、39秒節約できます。

その他のディレクトリ

他のディレクトリの要約リスト:

  • / bootは3秒節約します(ただし、私のものは非常に大きいです)
  • / devは3秒節約します
  • / runは4秒節約します
  • / varは8秒節約します
15