sortie brouillée lors de l'exécution de "xargs ls" en parallèle

Je veux listr tous les files dans /usr/ using ls . Je n'appelle pas directement ls , mais via xargs . De plus, j'utilise les parameters xargs -L et -P pour utiliser tous mes cœurs.

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

la command ci-dessus fonctionne comme prévu. Il produit une belle sortie. Cependant quand j'augmente le nombre de lignes -L paramètre de 16 à 64:

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

la sortie résultante est toute brouillée. Ce que je veux dire, c'est que la sortie ne commence plus sur la nouvelle ligne, les nouvelles lignes commencent au milieu de la ligne "précédente" et sont toutes mélangées:

 -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 

Ce qui est drôle, c'est que cela se produit uniquement avec l'utilisation de -L64 ou plus. Je ne vois pas ce problème avec -L16 .

Quelqu'un peut-il expliquer ce qui se passe ici?

Cela concerne les écritures sur les tuyaux. Avec -L16 vous exécutez un process pour chaque 16 files, ce qui produit environ un millier de caractères, en fonction de la longueur des noms de files. Avec -L64 vous êtes environ quatre mille. Le programme LS utilise presque certainement la bibliothèque stdio, et utilise presque certainement un buffer de 4kB pour la sortie afin de réduire le nombre d'appels en écriture.

Donc, find produit une charge de noms de files, alors (pour le cas -L64), xargs les découpe en packages de 64 et lance 4 process ls pour les gérer. Chaque ls va générer son premier 4k de sortie et l'écrire dans la pipe pour sortinger. Notez que ce 4k ne se terminera généralement pas par une nouvelle ligne. Alors disons que le troisième ls obtient son premier 4kB prêt d'abord, et il se termine

  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 

et puis le premier ls sort quelque chose, par exemple

  total 123459 

alors l'input à sortinger inclura lrwxrwxrwx 1 root root 6 Oct 2total 123459

Dans le cas de -L16 , les process ls ne produiront (habituellement) qu'un set complet de résultats en une seule fois.

Bien sûr, pour ce cas, vous perdez simplement du time et des ressources en utilisant xargs et ls, il vous suffit de find les informations qu'il contient déjà plutôt que d'exécuter des programmes supplémentaires pour refind les informations.

GNU Parallel a été construit pour résoudre exactement le problème de mixage (time d'exécution 40 secondes):

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

Il peut même détecter le nombre de coeurs (durée de fonctionnement 40 secondes):

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

Et répartissez l'input uniformément (durée de fonctionnement 24 secondes):

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