grep
命令选项
我想搜索整个驱动器以查找字符串。按照接受的答案堆栈溢出我用了:
sudo time grep -rnw '/' -e 'Sony 50"'
并且它53 小时在目前速度最快的 PCIe NVMe M.2 SSD 之一三星 Pro 960 上处理 20 GB 的数据。
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 所示。
的19.5 GiBLinux(Ubuntu 16.04.3 LTS)分区上使用的 43.8 GiB 空间中有一半是10 GB被内核使用。下载和测试内核是我的消遣。
这个测试占用了我大部分周末加上周一的时间来完成。
我怎样才能加快速度grep
并且仍然得到我想要的东西?
答案1
排除虚拟文件系统
查看示例输出日志,我们发现搜索中包含虚拟文件系统,这浪费了大量时间。使用此选项可将这些目录和其他目录从搜索中删除--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
更好的运行,并且单核 CPU 永远不会达到 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
保存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:
和),包含 105 GiB 数据E:
D:
HDD 上的一个 NTFS Windows 10 分区( ),包含 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 秒。通过排除包含 147 Gib 程序和数据的 Windows 10 分区节省21.5分钟!
将 Linux Header添加/usr/src
到排除列表
该/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 秒。/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 GB 的内核模块,我们的grep
时间是 36 秒。/lib/modules
通过指定modules
参数添加--exclude-dir
可节省 39 秒。
杂项目录
其他目录的汇总列表:
- /boot 节省了 3 秒(但我的特别大)
- /dev 节省 3 秒
- /run 节省 4 秒
- /var 节省 8 秒
答案2
以下接受的答案:
grep -nrilIF --exclude-dir={boot,dev,lib,media,mnt,proc,root,run,sys,/tmp,tmpfs,var} / -e "search term" 2>/dev/null
特别-我:处理二进制文件,就像它确实不是包含匹配数据,-F:将 PATTERNS 解释为固定字符串,而不是正则表达式-e(正则表达式)仍然需要声明要搜索的固定字符串