Supongamos que tengo la siguiente tubería:
a | b | c | d
¿Cómo puedo esperar para completar c
(o b
) en sh
o bash
? Esto significa que la secuencia de comandos d
puede iniciarse en cualquier momento (y no es necesario esperar), pero requiere que la salida completa de c
funcione correctamente.
El caso de uso es difftool
para git
comparar imágenes. Es invocado por git
y necesita procesar su entrada (la a | b | c
parte) y mostrar los resultados de la comparación (la d
parte). La persona que llama eliminará la entrada que se requiere para a
y b
. Esto significa que antes de regresar del script, el proceso c
(o b
) debe finalizar. Por otro lado, no puedo esperar d
porque esto significa que estoy esperando la entrada del usuario.
Sé que puedo escribir los resultados c
en un archivo temporal, o tal vez usar un FIFO en bash
. (Sin embargo, no estoy seguro si el FIFO ayudará). ¿Es posible lograr esto sin archivos temporales sh
?
EDITAR
Quizás sería suficiente si pudiera encontrar la identificación del proceso del c
(o b
) proceso de manera confiable. Entonces, toda la tubería podría iniciarse de forma asincrónica, y podría esperar una ID de proceso. Algo en la línea de
wait $(a | b | { c & [print PID of c] ; } | d)
EDITAR ^ 2
He encontrado una solución, los comentarios (o soluciones aún mejores) son bienvenidos.
d
comenzar a procesarc
la salida solo después de que sec
haya completado? ¿No desead
comenzar a procesar cada línea de salida tal como viene?d
es libre de comenzar cuando lo desee, peroc
debe terminar antes de que pueda seguir adelante.d
puede comenzar cuando le gusta, ¿qué está esperando exactamente?d
no utiliza la salida dec
, parece que no tiene sentido formard
parte de la tubería. Pero sid
usa la entrada, entoncesd
debe trabajar un poco en su entrada después de haberla leído todo para que su enfoque marque la diferencia.Respuestas:
La notificación se puede hacer, por ejemplo, mediante una señal a un PID que se ha pasado en una variable de entorno (
kill -USR1 $EXTPID
) o creando un archivo (touch /path/to/file
).Otra idea:
Ejecuta el siguiente proceso (el que puede comenzar a esperar) desde la tubería:
o
fuente
notify
podría ejecutarse antes de configurar la trampa de señal. ¿Cómo puedo asegurarme de no perder esa señal?trap
se haya definido.{ c; bg; }
o{ c; exit 0; }
no parece funcionar.Si entiendo su pregunta correctamente, esto debería funcionar:
(El truco de fd 3 se debe a que algunos (la mayoría) shells redirigen stdin a / dev / null with
&
).fuente
En bash, puedes usar una sustitución de proceso . El comando en la sustitución del proceso se ejecuta de forma asincrónica, no se espera.
fuente
bash
solo, ¿no essh
compatible?Esto es lo que he encontrado por prueba y error, con la ayuda de la aportación de Hauke:
Equivalentemente:
(Este último es más explícito, porque de
{}
todos modos se ejecutará en una subshell si está dentro de una tubería).Algunas otras señales (incluidas
QUIT
,TERM
yUSR1
) también funcionan, sin embargo, en este caso, la descripción de la señal se muestra en el terminal.Me pregunto si esta es la intención original de la
PIPE
señal. De acuerdo con el manual :Esto significa que cuando envío artificialmente una señal de tubería a la subshell, finaliza en silencio, dejando solo al consumidor final (
d
).Esto funciona en ambos
sh
ybash
.fuente
Puede usar el
sponge
programa desde el paquete "moreutils":a | b | c | sponge | d
la esponja será para el final de
c
la salida antes de conectarlad
. Espero que eso sea lo que querías.fuente
Solo puedes hacer:
Entonces, cuando
d
termina,cat
absorberá el resto dec
la producción hasta que termine.Okay. Después de los comentarios, creo que la respuesta es comenzar directamente
d
en segundo plano.Hacer:
o use la solución de Stephane Chazelas si hay problemas con la
d
lectura de stdin .fuente
c
termina antesd
y tengo que esperar hasta quec
termine, pero no me importad
.c
termine yd
siga funcionando? Matard
?d
tiene una GUI y puede ejecutarse hasta que el usuario la cierre.a
,b
yc
terminan su trabajo, cierran stdout y salen; y solod
sigue funcionando. ¿Quieres enviard
al fondo cuandoc
termine? ¿Es asi?d
debe enviarse a un segundo plano una vez quec
finalice.