'grep'ing todos os arquivos para uma string leva muito tempo

6

grep opções de comando

Eu queria pesquisar todo o meu disco por uma string. Seguindo a resposta aceita em estouro de pilha Eu usei:

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

e demorou 53 horas para processar 20 GB de dados em um dos mais rápidos SSD PCIe NVMe M.2; Samsung Pro 960.

grep log de saída

Quando grep processa alguns arquivos, gera mensagens de erro. Estes podem ser suprimidos anexando 2>/dev/null ao comando. No entanto, os erros dão feedback sobre o progresso que está sendo feito. Alguns dos exemplos de saída (tudo não vai caber) está abaixo:

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 dá impressão de que está congelado

Às vezes, eu achava que grep estava congelado porque a tela não foi atualizada por uma hora e a luz do disco rígido não pisca muito. No entanto Conky me diz que ainda está em execução e tendo 100% da CPU em um único núcleo, como visto neste GIF .

Do 19,5 GiB de 43,8 GiB sendo usado na partição Linux (Ubuntu 16.04.3 LTS), metade deste espaço, 10 GB é usado pelos kernels . Fazer o download e testar os kernels é o meu tempo de passagem.

Esse teste levou a maior parte do meu final de semana mais a segunda-feira para ser concluído.

Como posso acelerar grep e ainda obter o que estou procurando?

    
por WinEunuuchs2Unix 12.02.2018 / 13:08

1 resposta

15

Excluir sistemas de arquivos virtuais

Olhando para o log de saída de amostra, vemos que os sistemas de arquivos virtuais são incluídos na pesquisa, o que é um desperdício desnecessário de tempo. Elimine esses e outros diretórios da pesquisa com a opção --exclude-dir . Por exemplo:

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

Quando grep analisa a cadeia de diretórios /proc , ela está procurando inutilmente todos os IDs do processo que levam mais de um dia no meu caso.

Além disso, ao processar /mnt , ele estará procurando unidades USB e USBs montadas do Windows desnecessariamente.

/media is contém a unidade de CD / DVD e unidades USB externas.

Saída:

$ 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

Lá você vai 56 segundos ao invés de 50 horas !

Note que se você excluir usr (contendo 6.5 GB de arquivos no meu caso) da pesquisa, serão apenas 8 segundos:

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

Notas Interessantes

Manter os diretórios do sistema parece manter grep melhor e nunca atinge 100% da CPU em um único núcleo. Além disso, a luz do disco rígido pisca constantemente para que você saiba que grep está realmente funcionando e não "pensando em círculos".

Se você não prefixar tmp com / , ele ignorará qualquer subdiretório contendo tmp , por exemplo, /home/Me/tmp . Se você usar --exclude-dir /tmp , seu diretório /home/Me/tmp será pesquisado.

Se, por outro lado, você inserir o prefixo sys com / , o diretório /sys será pesquisado e os erros serão relatados. O mesmo é verdade para /proc . Então você tem que usar sys,proc e não prefixá-los com / . O mesmo vale para outros diretórios do sistema que testei.

Criar alias grepall

Considere a configuração de um alias em ~/.bashrc , para que você não precise digitar a lista de parâmetros --exclude-dir sempre:

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

Detalhamento detalhado do tempo

Esta seção detalha quanto tempo é economizado pela adição incremental de diretórios à lista de parâmetros --exclude-dir :

  • /proc e /sys saving 52 horas
  • /media saving 3 minutos
  • /mnt saving 21 minutos
  • /usr/src (especificando src ) salvando 53 segundos
  • /lib/modules (especificando modules ) salvando 39 segundos

Excluir /proc e /sys diretórios

Os diretórios /proc e /sys são os mais demorados, os mais inúteis para pesquisar e gerar a maioria dos erros. É "inútil" porque esses dois diretórios são criados dinamicamente em tempo de execução e não contêm arquivos permanentes que você gostaria de grep .

Uma grande economia de tempo é realizada excluindo-os:

$ 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

Apenas 27 minutos dessa vez economizando 52 horas !

Ainda há erros. No diretório /var , que também é um "diretório virtual" criado no tempo de execução. O diretório /run que contém um celular com Android e o diretório /media que contém um disco rígido antigo de laptop quebrado agora conectado a um HDD externo USB.

Adicione /media para excluir a lista

O diretório /media contém uma unidade de laptop antiga conectada via porta USB 3.0. O SmartCtl reporta diariamente erros na unidade e não possui arquivos que estamos procurando. Vamos excluí-lo para economizar tempo e reduzir as mensagens de erro:

$ 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

A exclusão do disco rígido com defeito conectado via compartimento USB 3.0 salvou apenas 3 minutos, mas reduziu as mensagens de erro.

Adicione /mnt (partições Windows NTFS) para excluir a lista

O diretório /mnt contém:

  • Duas partições NTFS Windows 10 ( C: e E: ) em um SSD com 105 GiB de dados
  • Uma partição NTFS Windows 10 ( D: ) em um disco rígido com 42 GiB de dados

Não há nada de interesse no Windows, por isso vamos excluir /mnt para poupar tempo:

$ 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

Agora, grep leva apenas 2 minutos e 8 segundos. Excluindo as partições do Windows 10 com 147 Gib de Programas e Dados economiza 21,5 minutos!

Adicione /usr/src Cabeçalhos do Linux para excluir lista

O diretório /usr/src contém o código-fonte do Linux Headers. No meu caso, há mais de 20 kernels instalados manualmente, o que ocupa um espaço considerável. Para especificar o diretório, embora o argumento usado seja 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

Agora, o grep leva apenas 1 minuto e 15 segundos. A exclusão de /usr/src especificando src na lista --exclude-dir economiza 53 segundos.

Adicione /lib/modules Kernel modules para excluir lista

O diretório /lib/modules contém módulos do kernel compilados. Para especificar o diretório, embora o argumento usado seja 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

Ao pular 6 GB de módulos do kernel, nosso tempo grep é de 36 segundos. Adicionar /lib/modules especificando modules no parâmetro --exclude-dir economiza 39 segundos.

Diretórios diversos

Lista de resumo de outros diretórios:

  • / boot salva 3 segundos (mas o meu é excepcionalmente grande)
  • / dev salva 3 segundos
  • / executar economiza 4 segundos
  • / var salva 8 segundos
por WinEunuuchs2Unix 12.02.2018 / 13:08