it-swarm.com.ru

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

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

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

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 GiB, используемых в разделе Linux (Ubuntu 16.04.3 LTS), половина этого пространства, 10 ГБ используются ядрами. Загрузка и тестирование ядер - мое время.


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

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

7
WinEunuuchs2Unix

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

Глядя на пример выходного журнала, мы видим, что виртуальные файловые системы включены в поиск, что является ненужной тратой времени. Удалите эти и другие каталоги из поиска с помощью опции --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% ЦП на одном ядре. Кроме того, индикатор жесткого диска постоянно мигает, поэтому вы знаете, что 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 экономия минуты
  • /mnt сохранение 21 минута
  • /usr/src (указав src) сохранение 53 секунды
  • /lib/modules (указав modules) сохранение 9 секунд

Исключить каталоги /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 GiB данными
  • Один раздел NTFS Windows 10 (D:) на жестком диске с 42 GiB данными

В 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 секунд
15
WinEunuuchs2Unix