Supposons que je veuille exécuter plusieurs programmes en parallèle et combiner leurs sorties dans un seul canal:
sh -c '
(echo qqq; echo qqq2; echo qqq3)&
(echo www; echo www2; echo www3)&
(echo eee; echo eee2; echo eee3)&
wait; wait; wait'
Cette approche shell fonctionne bien pour ce cas simple, mais je m'attends à ce qu'elle échoue si les programmes produisent plus de lignes plus longues de manière tamponnée, comme ceci (construit):
qqq
qqwww
q2
qqq3www2
wwweee3
eee2
eee3
L'une des solutions que j'ai été suggéré d'utiliser était tail -f
:
tail -n +0 -q -f <(echo qqq; echo qqq2; echo qqq3) <(echo www; echo www2; echo www3) <(echo eee; echo eee2; echo eee3)
, mais cette option n'est pas optimale: elle produit des données lentement, elle ne se termine pas; Je vois les sorties non pas dans l'ordre "sleep", mais dans l'ordre des arguments dans ce cas:
tail -n +0 -q -f <(sleep 1; echo qqq; sleep 1; echo qqq2; echo qqq3) <(echo www; echo www2; sleep 10; echo www3) <(echo eee; sleep 4; echo eee2; echo eee3) | cat
J'ai mis en place un petit programme spécial pour cela, mais je pense qu'il devrait y avoir un bon moyen standard de le faire.
Comment le faire en utilisant des outils standards (et sans tail -f
inconvénient)?
syslog
...syslog
n'est-elle pas pour les journaux, mais pour quelque chose de personnalisé considéré comme OK?-s
option pour la queue. Par exempletail -f -s .1 file
, le délai de boucle sera réduit à 0,1 seconde par rapport à la valeur par défaut de 1 seconde.Réponses:
GNU Parallel.
D'après les notes de version datées d'août 2013:
Par exemple:
parallel --line-buffer <jobs
Où
jobs
contient:short.sh
:long.sh
:Production:
la source
Une solution mettant en œuvre des verrous:
Il devrait y avoir un moyen plus rapide de créer un verrou que d'utiliser le système de fichiers.
la source
Je ne peux pas penser à quelque chose de simple, qui vous aidera, si vos lignes sont si longues, qu'un programme sera mis en veille avant d'avoir pu, pour terminer l'écriture d'une ligne sur stdout.
Cependant, si vos lignes sont suffisamment courtes pour être entièrement écrites avant la commutation de processus et que votre problème est que la génération d'une ligne prend très longtemps, vous pouvez mettre en mémoire tampon la sortie à l'aide de la lecture.
Par exemple:
la source
Vous pouvez créer un canal nommé avec
mkfifo
, vider toute la sortie dans le canal nommé et lire séparément à partir du canal nommé pour vos données collectées:la source
job1
et de lajob2
sortie de longues lignes (> 4096 octets)? Cela semble être nommé l'équivalent du premier exemple de code en question.tee
, qui ressemble exactement à ce que vous voulez. Regardez peut-être les composants internessyslog
ou d'autres outils de journalisation, car ils regroupent définitivement la sortie de plusieurs endroits dans un fichier journal. Le verrouillage peut également être la bonne réponse, comme l'a suggéré @emmanual.