Das "Grep" aller Dateien für einen String dauert lange

7

grep Befehlsoptionen

Ich wollte mein gesamtes Laufwerk nach einer Zeichenfolge durchsuchen. Nach der akzeptierten Antwort in Stack Overflow habe ich verwendet:

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

Die Verarbeitung von 20 GB Daten auf einer der schnellsten PCIe NVMe M.2-SSDs dauerte 53 Stunden . Samsung Pro 960.

grep Ausgabeprotokoll

Wenn grepeinige Dateien verarbeitet werden, werden Fehlermeldungen generiert. Diese können durch Anhängen 2>/dev/nullan den Befehl unterdrückt werden . Die Fehler geben jedoch Rückmeldung über die erzielten Fortschritte. Einige der Beispielausgaben (es passt nicht alles) sind unten aufgeführt:

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 macht den Eindruck, es ist gefroren

Manchmal dachte ich, ich grepsei eingefroren, weil der Bildschirm eine Stunde lang nicht aktualisiert wurde und die Festplattenanzeige nicht viel blinkte. Conky sagt mir jedoch, dass es immer noch läuft und 100% CPU auf einem einzelnen Kern benötigt, wie in diesem GIF gezeigt .

Von den 19,5 GiB von 43,8 GiB, die auf der Linux-Partition (Ubuntu 16.04.3 LTS) verwendet werden, wird die Hälfte dieses Speicherplatzes, 10 GB , von Kerneln verwendet. Das Herunterladen und Testen von Kerneln ist meine Freizeit.


Dieser Test dauerte den größten Teil meines Wochenendes plus Montag.

Wie kann ich beschleunigen grepund trotzdem das bekommen, wonach ich suche?

WinEunuuchs2Unix
quelle
3
In beiden Fällen ist es gut zu wissen, aber darf ich fragen, warum Sie überhaupt grepjede einzelne Datei auf dem Computer verwenden würden ? Ich finde einen Benutzerfall, in dem eigentlich nichts über den Pfad oder Namen der Datei bekannt ist, sehr schwer vorstellbar - wenn dies der Fall ist, sollte die findAusgabe von Piping grepmit parallel(oder die langsamere Alternative xargs) der richtige Weg sein.
Nachtisch
@dessert Unity über gnome-desktop zeigt einen vollständigen Monitornamen Sony 50 "an und ist nicht in xrandrder Liste" DP-1 "enthalten. Ich wollte die Datei finden, in der der vollständige Monitorname in der Gnome-Desktop-Engine gespeichert ist, auf die zugegriffen wurde hatte ohne Glück ausgiebig nach dem Dateinamen
gegoogelt
1
@ WinEunuuchs2Unix auch dann gibt es keinen Grund, das ganze / zu grep. /usrist ein perfekter Ausgangspunkt.
Muru
@muru Ja, es gibt viele goldene Nuggets, in denen ich abbauen kann /usr. In meinem Fall /usr/srcverlangsamt es sich, aber ich kann noch nicht herausfinden, wie ich das mit grep überspringen kann. Wie bei den anderen Komplikationen bei der /Handhabung. Ich muss mehr testen.
WinEunuuchs2Unix

Antworten:

15

Virtuelle Dateisysteme ausschließen

Wenn wir uns das Beispielausgabeprotokoll ansehen, sehen wir, dass virtuelle Dateisysteme in die Suche einbezogen werden, was eine unnötige Zeitverschwendung darstellt. Löschen Sie diese und andere Verzeichnisse mit der --exclude-dirOption aus der Suche . Zum Beispiel:

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

Wenn grepdie /procVerzeichniskette analysiert wird, werden alle Prozess-IDs nutzlos angezeigt, was in meinem Fall mehr als einen Tag dauert.

Auch bei der Verarbeitung /mntwerden unnötigerweise gemountete Windows NTFS-Laufwerke und USBs betrachtet.

/media Hier befinden sich das CD / DVD-Laufwerk und externe USB-Laufwerke.

Ausgabe:

$ 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

Los geht's 56 Sekunden statt 50 Stunden !

Hinweis: Wenn Sie usr(in meinem Fall 6,5 GB Dateien) von der Suche ausschließen, sind es nur 8 Sekunden:

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

Interessante Notizen

Das Heraushalten der Systemverzeichnisse scheint grepbesser zu bleiben und trifft niemals 100% der CPU auf einem einzelnen Kern. Außerdem blinkt die Festplattenanzeige ständig, damit Sie wissen, dass sie grepwirklich funktioniert und nicht "im Kreis denkt".

Wenn Sie nicht das Präfix tmpmit /dann wird es jedes Unterverzeichnis enthält , ignoriert tmpzum Beispiel /home/Me/tmp. Wenn Sie --exclude-dir verwenden, /tmpwird Ihr Verzeichnis /home/Me/tmpdurchsucht.

Wenn auf der anderen Seite Sie Präfix sysmit /dann dann /sysVerzeichnis wird durchsucht und Fehler gemeldet. Gleiches gilt für /proc. Sie müssen sie also verwenden sys,procund nicht voranstellen /. Gleiches gilt für andere Systemverzeichnisse, die ich getestet habe.

Alias ​​erstellen grepall

Richten Sie einen Alias ​​ein, ~/.bashrcdamit Sie die --exclude-dirParameterliste nicht jedes Mal eingeben müssen:

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

Detaillierte Zeitaufschlüsselung

In diesem Abschnitt wird beschrieben, wie viel Zeit gespart wird, indem der --exclude-dirParameterliste schrittweise Verzeichnisse hinzugefügt werden:

  • /procund 52 Stunden/sys sparen
  • /media3 Minuten sparen
  • /mnt21 Minuten sparen
  • /usr/src(durch Angabe src) 53 Sekunden sparen
  • /lib/modules(durch Angabe modules) 39 Sekunden sparen

Ausschluss /procund /sysVerzeichnisse

Die Verzeichnisse /procund /syssind am zeitaufwändigsten und am nutzlosesten, um die meisten Fehler zu suchen und zu generieren. Es ist "nutzlos", da diese beiden Verzeichnisse zur Laufzeit dynamisch erstellt werden und keine permanenten Dateien enthalten, die Sie möchten grep.

Eine große Zeitersparnis wird erzielt, indem sie ausgeschlossen werden:

$ 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

Nur 27 Minuten, diesmal über 52 Stunden !

Es gibt jedoch immer noch Fehler. In einem /varVerzeichnis, das auch ein zur Laufzeit erstelltes "virtuelles Verzeichnis" ist. Das /runVerzeichnis, das ein Android-Handy enthält, und das /mediaVerzeichnis, das eine alte kaputte Laptop-Festplatte enthält, die jetzt an ein externes USB-Festplattengehäuse angeschlossen ist.

Hinzufügen /media, um die Liste auszuschließen

Das /mediaVerzeichnis enthält ein altes Laptop-Laufwerk, das über einen USB 3.0-Anschluss angeschlossen ist. Smartctl meldet täglich Fehler auf dem Laufwerk und verfügt nicht über die gesuchten Dateien. Wir werden es ausschließen, um Zeit zu sparen und Fehlermeldungen zu reduzieren:

$ 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

Mit Ausnahme der fehlerhaften Festplatte, die über ein USB 3.0-Gehäuse angeschlossen ist, wurden nur 3 Minuten eingespart, aber weniger Fehlermeldungen angezeigt.

Hinzufügen /mnt(Windows NTFS-Partitionen) zum Ausschließen der Liste

Das /mntVerzeichnis enthält:

  • Zwei NTFS Windows 10-Partitionen ( C:und E:) auf einer SSD mit 105 GB Daten
  • Eine NTFS Windows 10-Partition ( D:) auf einer Festplatte mit 42 GB Daten

Windows ist nicht von Interesse, daher schließen wir aus /mnt, um Zeit zu sparen:

$ 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

Jetzt grepdauert es nur noch 2 Minuten und 8 Sekunden. Durch das Ausschließen von Windows 10-Partitionen mit 147 Gib an Programmen und Daten werden 21,5 Minuten eingespart!

Fügen Sie /usr/srcLinux-Header hinzu, um die Liste auszuschließen

Das /usr/srcVerzeichnis enthält den Quellcode von Linux Headers. In meinem Fall sind mehr als 20 Kernel manuell installiert, was viel Platz beansprucht. So geben Sie das Verzeichnis an, obwohl das verwendete Argument lautet 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

Jetzt dauert grep nur noch 1 Minute und 15 Sekunden. Das Ausschließen /usr/srcdurch Angabe srcin der --exclude-dirListe spart 53 Sekunden.

Fügen Sie /lib/modulesKernelmodule hinzu, um die Liste auszuschließen

Das /lib/modulesVerzeichnis enthält kompilierte Kernelmodule. So geben Sie das Verzeichnis an, obwohl das verwendete Argument lautet 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

Durch das Überspringen von 6 GB Kernelmodulen grepbeträgt unsere Zeit 36 ​​Sekunden. Das Hinzufügen /lib/modulesdurch Angabe modulesim --exclude-dirParameter spart 39 Sekunden.

Verschiedene Verzeichnisse

Zusammenfassende Liste anderer Verzeichnisse:

  • / boot spart 3 Sekunden (aber meine ist außergewöhnlich groß)
  • / dev spart 3 Sekunden
  • / run spart 4 Sekunden
  • / var spart 8 Sekunden
WinEunuuchs2Unix
quelle
4
Beachten Sie, dass --exclude-dir=tmpjedes tmpVerzeichnis an einer beliebigen Stelle im Verzeichnisbaum ausgeschlossen wird. Also würde ich eher ausdrücklich empfehlen, die Verzeichnisse von der Wurzel auflisten , die sind grep werden, zum Beispiel grep -r pattern /bin /etc /home ....
Egmont
@egmont habe ich getestet tmpund sicher auch ausgeschlossen /home/Me/tmp. Dies wurde behoben, indem /tmpin `` exclude-dir . However if I used / sys` in exclude-dir verwendet wurde. Dann wurde es durchsucht, sodass es sysstattdessen so eingestellt werden musste. Sehr eigenartig. Vielen Dank für Ihre Eingabe und ich bin so froh, dass dieses langwierige Projekt vorbei ist :)
WinEunuuchs2Unix