详细时间细分

详细时间细分

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(正则表达式)仍然需要声明要搜索的固定字符串

相关内容