并行运行“xargs ls”时输出乱码

并行运行“xargs ls”时输出乱码

我想列出/usr/使用中的所有文件ls。我不是ls直接打电话,而是通过xargs。此外,我正在使用xargs参数-L-P利用我的所有核心。

find /usr/ -type f  -print0 | xargs -0 -L16 -P4 ls -lAd  | sort -k9 > /tmp/aaa

上面的命令按预期工作。它产生很好的输出。但是,当我将行数参数-L从 16 增加到 64 时:

find /usr/ -type f  -print0 | xargs -0 -L64 -P4 ls -lAd  | sort -k9 > /tmp/bbb

结果输出全是乱码。我的意思是,输出不再从新行开始,新行从“上一行”的中间开始,并且全部混合在一起:

-rw-r--r-- 1 root root  5455 Nov 16  2010 /usr/shareonts/X11/encodings/armscii-8.enc.gz
-rw-r--r-- 1 root root  1285 May 29  2016-rw-r--r-- 1 root root   6205 May 29  2016 /usr/include/arpa/nameser_compat.h
-rw-r--r-- 1 root root       0 Apr 17  20-rw-r--r-- 1 root root   933 Apr 16  2012 /usr/share/icons/nuoveXT2/16x16/actions/address-book-new.png
-rw-r--r-- 1 root root  53651 Jun 17  2012-rw-r--r-- 1 root root  7117 May 29  2016 /usr/include/dlfcn.h
-rw-r--r-- 1 root root  311 Jun  9  2015-rw-r--r-- 1 root root 1700 Jun  9  2015 /usr/share/cups/templates/de/add-printer.tmpl
-rw-r--r-- 1 root root  5157 M1 root root 10620 Jun 14  2012 /usr/lib/perl5/Tk/pTk/tkIntXlibDecls.m
-rw-r--r-- 1 root -rwxr-xr-x 1 root root    1829 Jan 22  2013 /usr/lib/emacsen-common/packages/install/dictionaries-common
-rw-r--r-- 1 root r-rw-r--r-- 1 root root  1890 Jun  2  2012 /usr/share/perl5/Date/Manip/TZ/afaddi00.pm
-rw-r--r-- 1 root root 1104 Jul-rw-r--r-- 1 root root  10268 Jul 27 15:58 /usr/share/perl/5.14.2/B/Debug.pm
-rw-r--r-- 1 root root  725 Apr  1-rw-r--r-- 1 root root  883 Apr  1  2012 /usr/share/icons/gnome/16x16/actions/address-book-new.png

有趣的是,它只在使用-L64或更大时发生。我没有看到这个问题-L16

有人能解释一下这里发生了什么吗?

答案1

这与写入管道有关。您正在-L16为每 16 个文件运行一个进程,这会产生大约一千个字符,具体取决于文件名的长度。和-L64你在一起的大约有四千人。该ls程序几乎肯定使用了 stdio 库,并且几乎肯定使用 4kB 缓冲区进行输出,以减少写入调用的次数。

因此 find 会生成大量文件名,然后(对于 -L64 情况)xargs 将它们分成 64 个文件名,并启动 4 个ls进程来处理它们。每个ls都会生成其前 4k 输出并将其写入管道进行排序。请注意,此 4k 通常会不是以换行符结束。所以说第三个ls首先准备好它的第一个 4kB,然后结束

 lrwxrwxrwx 1 root root       6 Oct 21  2013 bzegrep -> bzgrep
 -rwxr-xr-x 1 root root    4877 Oct 21  2013 bzexe
 lrwxrwxrwx 1 root root       6 Oct 2

然后第一个 ls 输出一些内容,例如

 total 123459

那么排序的输入将包括lrwxrwxrwx 1 root root 6 Oct 2total 123459

在这种-L16情况下,ls进程(通常)只会一次性输出一组完整的结果。

当然,对于这种情况,使用 xargs 和 ls 只是浪费时间和资源,您应该只输出find已有的信息,而不是运行额外的程序来再次发现信息。

答案2

GNU Parallel 的构建是为了精确解决混合问题(运行时间 40 秒):

find /usr/ -type f  -print0 | parallel -0 -L64 -P4 ls -lAd  | sort -k9 > /tmp/bbb

它甚至可以检测核心数量(运行时间 40 秒):

find /usr/ -type f -print0 | parallel -0 -L64 ls -lAd  | sort -k9 > /tmp/bbb

并均匀地分割输入(运行时间 24 秒):

find /usr/ -type f -print0 | parallel -0 -X ls -lAd  | sort -k9 > /tmp/bbb

相关内容