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

Mar*_*ter 5 ls find xargs sort

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

find /usr/ -type f  -print0 | xargs -0 -L16 -P4 ls -lAd  | sort -k9 > /tmp/aaa
Run Code Online (Sandbox Code Playgroud)

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

find /usr/ -type f  -print0 | xargs -0 -L64 -P4 ls -lAd  | sort -k9 > /tmp/bbb
Run Code Online (Sandbox Code Playgroud)

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

-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
Run Code Online (Sandbox Code Playgroud)

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

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

ica*_*rus 5

这与写入管道有关。随着-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
Run Code Online (Sandbox Code Playgroud)

然后第一个 ls 输出一些东西,例如

 total 123459
Run Code Online (Sandbox Code Playgroud)

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

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

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