web-dev-qa-db-fra.com

`grep`ing tous les fichiers d'une chaîne prend beaucoup de temps

grep options de commande

Je voulais chercher une chaîne dans tout mon lecteur. Suite à la réponse acceptée en débordement de pile j'ai utilisé:

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

et il a fallu 53 heures pour traiter 20 Go de données sur l'un des disques SSD PCIe NVMe M.2 les plus rapides du marché; Samsung Pro 960.

grep log de sortie

Lorsque grep traite certains fichiers, il génère des messages d'erreur. Ceux-ci peuvent être supprimés en ajoutant 2>/dev/null à la commande. Cependant, les erreurs donnent des informations sur les progrès accomplis. Une partie de l'exemple de sortie (tout ne convient pas) est ci-dessous:

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 donne l'impression qu'il est gelé

Parfois, je pensais que grep était gelé car l'écran ne se mettait pas à jour pendant une heure et le voyant du disque dur ne clignotait pas beaucoup. Cependant, Conky me dit qu'il est toujours en cours d'exécution et qu'il prend 100% de la CPU sur un seul cœur, comme on le voit dans ce GIF .

Parmi les 19,5 Gio sur 43,8 GiB utilisés sur la partition Linux (Ubuntu 16.04.3 LTS), la moitié de cet espace , 10 GB sont utilisés par les noyaux. Télécharger et tester les noyaux est mon passe-temps.


Ce test a duré presque toute ma fin de semaine et lundi.

Comment puis-je accélérer grep et toujours obtenir ce que je recherche?

7
WinEunuuchs2Unix

Exclure les systèmes de fichiers virtuels

En examinant l'exemple de journal de sortie, nous constatons que les systèmes de fichiers virtuels sont inclus dans la recherche, ce qui représente une perte de temps inutile. Supprimez ces répertoires et d'autres de la recherche avec l'option --exclude-dir. Par exemple:

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

Lorsque grepanalyse la chaîne de répertoires /proc, il examine inutilement tous les ID de processus, ce qui prend plus d'une journée dans mon cas.

De même, lors du traitement de /mnt, il examinera inutilement les lecteurs Windows NTFS montés et les clés USB.

/media contient le lecteur de CD/DVD et les lecteurs USB externes.

Sortie:

$ 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

Voilà 56 secondes au lieu de 50 heures!

Notez que si vous excluez usr(contenant 6,5 Go de fichiers dans mon cas) de la recherche, il ne reste que 8 secondes:

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

Notes intéressantes

Garder les répertoires système semble garder grepsur une meilleure piste et il ne frappe jamais à 100% de la CPU sur un seul cœur. De plus, le voyant du disque dur clignote en permanence pour que vous sachiez que grepfonctionne réellement et ne "pense pas en cercles".

Si vous ne préfixez pas tmpavec /, il ignorera tout sous-répertoire contenant tmpname__, par exemple /home/Me/tmp. Si vous utilisez --exclude-dir /tmp, votre répertoire /home/Me/tmp sera recherché.

Si, par contre, vous préfixez sysavec /, le répertoire /sys est alors recherché et des erreurs sont signalées. Il en va de même pour /proc. Vous devez donc utiliser sys,proc et ne pas les préfixer avec /. Il en va de même pour les autres répertoires système que j'ai testés.

Créer un alias grepallname__

Pensez à configurer un alias dans ~/.bashrc afin de ne pas avoir à taper la liste de paramètres --exclude-dir à chaque fois:

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

Répartition détaillée du temps

Cette section détaille le temps gagné en ajoutant des répertoires à la liste de paramètres --exclude-dir:

  • /proc and /sys save 52 hours
  • /media save minutes
  • /mnt saving 21 minutes
  • /usr/src (en spécifiant srcname__) save 53 seconds
  • /lib/modules (en spécifiant modulesname__) save 9 seconds

Exclure les répertoires /proc et /sys

Les répertoires /proc et /sys exigent le plus de temps et de recherche et génèrent le plus d'erreurs. C'est "inutile" parce que ces deux répertoires sont créés dynamiquement au moment de l'exécution et ne contiennent pas de fichiers permanents que vous voudriez grepname__.

Un gain de temps considérable est réalisé en les excluant:

$ 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

Seulement 27 minutes cette économie de temps sur 52 heures!

Il y a encore des erreurs cependant. Dans le répertoire /var qui est également un "répertoire virtuel" créé au moment de l'exécution. Le répertoire /run qui contient un téléphone cellulaire Android et le répertoire /media qui contient un ancien disque dur d'ordinateur portable brisé, à présent connecté à un boîtier de disque dur externe USB.

Ajouter /media à la liste d'exclusion

Le répertoire /media contient un ancien lecteur d’ordinateur portable connecté via le port USB 3.0. Smartctl rapporte quotidiennement des erreurs sur le lecteur et ne contient pas les fichiers que nous recherchons. Nous allons l'exclure pour gagner du temps et réduire les messages d'erreur:

$ 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

À l'exclusion du disque dur défectueux connecté via USB 3.0, le boîtier n'a économisé que 3 minutes, mais les messages d'erreur ont été réduits.

Ajouter /mnt (partitions Windows NTFS) à la liste d'exclusion

Le répertoire /mnt contient:

  • Deux partitions NTFS Windows 10 (C: et E:) sur un disque SSD avec 105 GiB de données
  • Une partition NTFS Windows 10 (D:) sur un disque dur avec 42 GiB de données

Windows ne présente aucun intérêt; nous allons donc exclure /mnt pour gagner du temps:

$ 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

Maintenant, grepne prend que 2 minutes et 8 secondes. En excluant les partitions Windows 10 avec 147 gib de programmes et de données enregistre 21,5 minutes!

Ajouter /usr/src Linux Headers à la liste d'exclusion

Le répertoire /usr/src contient le code source des en-têtes Linux. Dans mon cas, il y a plus de 20 noyaux installés manuellement, ce qui prend un espace considérable. Pour spécifier le répertoire bien que l'argument utilisé soit srcname__:

$ 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

Maintenant, grep ne prend que 1 minute et 15 secondes. Exclure /usr/src en spécifiant srcdans la liste --exclude-dir enregistre 53 secondes.

Ajoutez /lib/modules modules du noyau à la liste d'exclusion

Le répertoire /lib/modules contient des modules de noyau compilés. Pour spécifier le répertoire bien que l'argument utilisé soit modulesname__:

$ 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

En ignorant 6 Go de modules du noyau, notre temps grepest de 36 secondes. Ajouter /lib/modules en spécifiant modulesdans le paramètre --exclude-dir enregistre 39 secondes.

Répertoires divers

Liste récapitulative des autres répertoires:

  • / boot enregistre 3 secondes (mais la mienne est exceptionnellement grande)
  • / dev enregistre 3 secondes
  • / run sauve 4 secondes
  • / var sauve 8 secondes
15
WinEunuuchs2Unix