Según su documentación, bash espera hasta que todos los comandos en una tubería hayan terminado de ejecutarse antes de continuar
El shell espera a que finalicen todos los comandos de la canalización antes de devolver un valor.
Entonces, ¿por qué el comando yes | true
termina de inmediato? ¿No debería el yes
bucle para siempre y hacer que la tubería nunca regrese?
Y una pregunta secundaria: de acuerdo con la especificación POSIX , las tuberías de shell pueden elegir regresar después de que finalice el último comando o esperar hasta que finalicen todos los comandos. ¿Las conchas comunes tienen un comportamiento diferente en este sentido? ¿Hay algún caparazón donde yes | true
se repita para siempre?
yes | tee >(true) >/dev/null
hará lo que espera, por cierto,tee
hasta que todos los escritores estén muertos, por lo quetrue
salir no lo interrumpirá por completo.true
es básicamente un{return 0;}
programa, por lo que no esperaría que se ejecute por mucho tiempo, y mucho menos para siempre.Respuestas:
Cuando
true
sale, el lado de lectura de la tubería está cerrado, peroyes
continúa intentando escribir en el lado de escritura. Esta condición se denomina "tubería rota" y hace que el núcleo envíe unaSIGPIPE
señalyes
. Comoyes
no hace nada especial con esta señal, será eliminada. Si ignoró la señal, eswrite
llamada fallará con el código de errorEPIPE
. Los programas que hacen eso deben estar preparados para notarEPIPE
y dejar de escribir, o entrarán en un ciclo infinito.Si lo haces
strace yes | true
1 puedes ver el kernel preparándose para ambas posibilidades:strace
está viendo eventos a través de la API del depurador, que primero le informa sobre la devolución de la llamada del sistema con un error y luego sobre la señal. Sinyes
embargo, desde la perspectiva, la señal ocurre primero. (Técnicamente, la señal se entrega después de que el núcleo devuelve el control al espacio del usuario, pero antes de que se ejecuten más instrucciones de la máquina, por lo que elwrite
"wrapper" en la biblioteca C no tiene la oportunidad de establecererrno
y volver a la aplicación).1 Lamentablemente,
strace
es específico de Linux. La mayoría de los Unix modernos tienen algún comando que hace algo similar, pero a menudo tiene un nombre diferente, probablemente no decodifique los argumentos de syscall tan a fondo, y a veces solo funciona para root.fuente
yes
está conectado a la tubería.yes
obtener SIGPIPE, ya que el FD en el que está escribiendo no está conectado a una tubería.yes >/dev/null
se repite para siempre. No demuestra nada en absoluto sobre las tuberías que no son también ciertas para los comandos simples (como el comportamiento de espera de terminación que Tom señala también es cierto para los comandos simples).write()
(la función en libc) no regresa (transfiere el control a la PC después de eso) hasta después el controlador de señal se ha ejecutado, pero como el controlador de señal finaliza el programa, el control nunca se transfiere y, por lo tanto,write()
nunca regresa. Sí, eso se implementa en el núcleo al tener algunaxxx_write()
función de retorno-EPIPE
, pero estamos depurando un programa de espacio de usuario y sin interés en eso.Es poco probable, ya que el
yes
comando está usando la tubería, y fallará cuando la tubería se rompa.sleep
por otro lado, no usa la tubería, entonces:correrá por 100000000 segundos, al menos.
fuente
true
está un incorporado. Esto se aplica a las versiones recientes delBourne Shell
,ksh93
,zsh
. Si presiona^Z
cuando se ejecuta un comando de este tipo, se suspenderá la suspensión y el shell nunca podrá recuperarse sin ayuda externa.sbrk()
. Una versión portátil y mantenida está en el paquete de herramientas schily y @Charles Duffy ya descubrió una ubicación para obtener información ;-)bsh
(Berthold Shell de VBERTOS, una versión mejorada de memoria virtual de UNOS - el primer clon de UNIX). Bsh obtuvo muchas características de csh en 1984 y 1985, pero el mecanismo de alias de UNOS ya era superior al de csh en 1980. Otras características nuevas de Bourne Shell son de POSIX, para permitir que se acerque al cumplimiento de POSIX.