Supongamos que quiero ejecutar varios programas en paralelo y combinar sus salidas en una tubería:
sh -c '
(echo qqq; echo qqq2; echo qqq3)&
(echo www; echo www2; echo www3)&
(echo eee; echo eee2; echo eee3)&
wait; wait; wait'
Este enfoque de shell funciona bien para este caso simple, pero espero que falle si los programas generan más y más líneas de forma amortiguada, como este (construido):
qqq
qqwww
q2
qqq3www2
wwweee3
eee2
eee3
Una de las soluciones que se me sugirió usar fue 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)
, pero esta es una opción subóptima: emite datos lentamente, no termina; Veo salidas no en orden de "suspensión", sino en orden de argumentos en este caso:
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
He implementado un pequeño programa especial para esto, pero creo que debería haber alguna buena forma estándar de hacerlo.
¿Cómo hacerlo usando herramientas estándar (y sin tail -f
desventajas)?
syslog
...syslog
no para registros, sino para algo personalizado considerado correcto?-s
opción de cola. por ejemplotail -f -s .1 file
, reducirá el retraso del bucle a .1 segundos desde el valor predeterminado de 1 segundo.Respuestas:
GNU Paralelo
De las notas de la versión de agosto de 2013:
Por ejemplo:
parallel --line-buffer <jobs
Donde
jobs
contiene:short.sh
:long.sh
:Salida:
fuente
Una solución que implementa bloqueos:
Debería haber una forma más rápida de crear un bloqueo que usar el sistema de archivos.
fuente
No puedo pensar en nada simple, que te ayudará, si tus líneas son tan largas, que un programa se enviará a dormir antes de que pueda, para terminar de escribir una línea en stdout.
Sin embargo, si sus líneas son lo suficientemente cortas como para escribirlas completamente antes del cambio de proceso, y su problema es que generar una línea lleva mucho tiempo, puede almacenar la salida en buffer usando la lectura.
P.ej:
fuente
Puede hacer una tubería con nombre
mkfifo
, volcar toda la salida en la tubería con nombre y leer por separado de la tubería con nombre para sus datos recopilados:fuente
job1
yjob2
genere líneas largas (> 4096 bytes)? Esto parece llamarse equivalente de canalización del primer ejemplo de código en la consulta.tee
, que suena exactamente como lo que quieres. Posiblemente observe lassyslog
partes internas u otras herramientas de registro, porque definitivamente agregan la salida de varios lugares en un archivo de registro. El bloqueo también puede ser la respuesta correcta, como sugirió @emmanual, también.