proceso de fondo de entrada de tubería

14

si quiero mostrar "aaa" en la pantalla:

(1)$: echo aaa | cat                 ... works OK
(2)$: echo aaa | ( cat )             ... works OK
(3)$: echo aaa | ( cat & )           ... NOT working
(4)$: ( echo aaa & ) | cat           ... works OK 
(5)$: echo aaa | ( cat <&0 & )       ... works ok in BASH (but not in SH)
(6)$: echo aaa | ( cat <&3 & ) 3<&0  ... works ok in BASH and SH

La exclusión de (3) y (4) -> proceso separado todavía tiene una salida conectada que puede ser controlada, utilizada, redirigida ... ¡pero no entrada!

Mi pregunta es: ¿alguien entiende por qué y cómo funciona la línea (5) ?

... "<& 0" es la abreviatura de "0 <& 0", por qué redirigir 0 a 0 es la solución, y lo que realmente sucede detrás con la entrada del proceso separado. Los subshell no son el problema, usar llaves {...} en lugar de (...) proporciona los mismos resultados.

... y pregunta2: ¿hay una mejor solución para "dar entrada al proceso separado" que la línea (6).

Asain Kujovic
fuente

Respuestas:

12

Sí, como lo requiere POSIX , los comandos comenzaron en segundo plano con& tienen su entrada estándar redirigida desde /dev/null.

Y de hecho

{ cmd <&3 3<&- & } 3<&0

es la forma más obvia de solucionarlo.

Sin embargo, no está claro por qué querría ejecutar parte de la tubería en segundo plano.

Stéphane Chazelas
fuente
la razón era obtener el PID de un comando específico dentro de la cadena de tubería (cmd1 | {cmd2 &; pid2 = $ !;} | cmd3 ..., entonces / dev / null == & 0 es estándar para el proceso de BG, también sabe por qué "0 <& 0" funciona en bash ... ¿y es seguro?
Asain Kujovic
3
@OmerMerdan POSIX dice: En todos los casos, la redirección explícita de la entrada estándar anulará esta actividad , lo que contradice de alguna manera lo que dijo anteriormente, por lo que creo que la bashinterpreta (y eso suena como una interpretación razonable) como cancelar la /dev/nullredirección. Ahora, no muchas conchas hacen lo mismo. Ash y pdksh no.
Stéphane Chazelas
¿Por qué 3<&-necesita la pieza y es seguro usarla (no cerrará la tubería antes de que se lea la entrada completa)?
mvorisek
1
@Mvorisek, que fd 3 solo se usa temporalmente para restaurar el stdin original. Lo cerramos porque cmdno lo necesita. Lo cerramos después de haberlo duplicado en fd 0 ( <&3abreviatura de 0<&3).
Stéphane Chazelas
1
@Mvorisek, nohuptambién redirige la entrada estándar a / dev / null, por lo que se necesitaría: { nohup sh -c 'cmd <&3 3<&-' & } 3<&0. O(trap '' HUP; cmd <&3 3<&- > nohup.out 2>&1 &) 3<&0
Stéphane Chazelas