`grep` для всех файлов для строки занимает много времени

grep параметры команды

Я хотел обыскать весь мой диск на предмет наличия строки. После принятого ответа в Stack Overflow я использовал:

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

и потребовалось 53 часа для обработки 20 ГБ данных на одном из самых быстрых SSD-накопителей PCIe NVMe M.2; 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 создается впечатление, что он заморожен

Иногда я думал grep был заморожен, потому что экран не обновлялся в течение часа, а индикатор жесткого диска не мигал. Однако Конки говорит мне, что он все еще работает и использует 100% ЦП на одном ядре, как показано в этом GIF.

Из 19,5 ГБ из 43,8 ГБ, используемых в разделе Linux (Ubuntu 16.04.3 LTS), половина этого пространства, 10 ГБ, используется ядрами. Загрузка и тестирование ядер - мое время.


Этот тест занял большую часть моего уик-энда плюс понедельник.

Как я могу ускорить grep и все еще получить то, что я ищу?

2 ответа

Решение

Исключить виртуальные файловые системы

Глядя на пример выходного журнала, мы видим, что виртуальные файловые системы включены в поиск, что является ненужной тратой времени. Удалите эти и другие каталоги из поиска с помощью --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 Цепочка каталогов бесполезно просматривает все идентификаторы процессов, что в моем случае занимает больше суток.

Также при обработке /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 ГБ файлов в моем случае) из поиска это всего 8 секунд:

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

Интересные заметки

Хранение системных каталогов, кажется, сохраняет grep на лучшем треке, и он никогда не достигает 100% CPU на одном ядре. Кроме того, индикатор жесткого диска постоянно мигает, чтобы вы знали, grep действительно работает, а не "думать по кругу".

Если вы не префикс tmp с / тогда он будет игнорировать любой подкаталог, содержащий tmp например /home/Me/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 экономия 3 минуты
  • /mnt экономия 21 минут
  • /usr/src (указав src) экономия 53 секунд
  • /lib/modules (указав modules) экономия 39 секунд

исключать /proc а также /sys каталоги

/proc а также /sys каталоги являются самыми трудоемкими, наиболее бесполезными для поиска и генерации большинства ошибок. Это "бесполезно", потому что эти два каталога динамически создаются во время выполнения и не содержат постоянных файлов, которые вы хотели бы 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 каталог, который также является "виртуальным каталогом", созданным во время выполнения. /run каталог, который содержит мобильный телефон Android и /media каталог, в котором находится старый сломанный жесткий диск ноутбука, теперь подключенный к внешнему жесткому диску USB.

добавлять /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 каталог содержит:

  • Два раздела NTFS для Windows 10 (C: а также E:) на SSD с 105 ГиБ данных
  • Один раздел NTFS для Windows 10 (D:) на жестком диске с 42 ГиБ данных

В 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 секунд. Исключение разделов Windows 10 с 147 Gib программ и данных экономит 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 ГБ модулей ядра, наш grep время 36 секунд. Добавление /lib/modules указав modules в --exclude-dir Параметр экономит 39 секунд.

Разные каталоги

Сводный список других каталогов:

  • / boot экономит 3 секунды (но мой очень большой)
  • / dev экономит 3 секунды
  • / запустить экономит 4 секунды
  • / Var экономит 8 секунд

После принятого ответа:

      grep -nrilIF --exclude-dir={boot,dev,lib,media,mnt,proc,root,run,sys,/tmp,tmpfs,var} / -e "search term" 2>/dev/null

в частности -I : обрабатывать двоичный файл так, как если бы он не содержал совпадающих данных, -F : интерпретировать ШАБЛОНЫ как фиксированные строки, а не регулярные выражения с -e (регулярное выражение), по-прежнему требуется указать фиксированную строку для поиска

Другие вопросы по тегам