`grep`ing字符串的所有文件需要很长时间

grep命令选项

我想在整个驱动器中搜索一个字符串。 根据Stack Overflow中接受的答案,我使用了:

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

在最快的PCIe NVMe M.2固态硬盘之一上花了53个小时来处理20 GB的数据; 三星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被冻结是因为屏幕没有更新一小时而且硬盘灯没有闪烁太多。 然而,Conky告诉我它仍在运行并且在单核上占用100%CPU ,如此GIF中所示 。

在Linux(Ubuntu 16.04.3 LTS)分区中使用的43.8 GiB中的19.5 GiB中 ,内核使用了一半的空间, 10 GB 。 下载和测试内核是我的通行时间。


这个测试花了我周末和周一的大部分时间来完成。

我怎样才能加速grep并仍然得到我正在寻找的东西?

排除虚拟文件系统

查看示例输出日志,我们看到搜索中包含虚拟文件系统,这是不必要的浪费时间。 使用--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目录链时,它无用地查看所有进程ID,在我的情况下需要超过一天。

此外,当处理/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 GB的文件),它只有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目录包含:

  • SSD上有两个NTFS Windows 10分区( C:E: :),具有105 GiB数据
  • 一个NTFS Windows 10分区( D: :)在具有42 GiB数据的HDD上

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秒。 通过使用147 Gib程序和数据排除Windows 10分区可节省21.5分钟!

添加/usr/src Linux标头以排除列表

/usr/src目录包含Linux Headers源代码。 在我的情况下,手动安装了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秒。 通过在--exclude-dir列表上指定src来排除/usr/src可以节省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 GB的内核模块,我们的grep时间为36秒。 通过在--exclude-dir参数中指定modules来添加/lib/modules可以节省39秒。

杂项目录

其他目录的摘要列表:

  • / boot节省3秒(但我的特别大)
  • / dev节省3秒
  • / run节省4秒
  • / var节省8秒