¿Es seguro escribir otro comando en STDIN mientras el comando anterior está escribiendo en STDOUT?

21

Quizás esto haya sido respondido previamente, agradecería un enlace a otra respuesta ...

Si ejecuto un comando de shell (en un bashshell) como el siguiente:

make

Luego, mientras la salida de makese desplaza desde STDOUTdel makecomando, si escribo make checky presiono enterantes de que el primer comando termine de ejecutarse, cuando el makecomando finalmente termine, el siguiente comando make checkse levantará y se ejecutará.

Mis preguntas son simplemente:

  1. ¿Es peligroso hacer esto?
  2. ¿Hay posibles comportamientos inesperados de este tipo de escritura rápida?
  3. ¿Por qué funciona esto como lo hace?
111 ---
fuente
2
1. Espero que no ... ¡He estado haciendo esto durante años!
John WH Smith

Respuestas:

20

Funciona de la manera que lo hace porque Unix es full-duplex. Como dijo Ritchie en El sistema de tiempo compartido UNIX: una retrospectiva :

Una cosa que parece trivial, pero que marca una diferencia sorprendente una vez que uno está acostumbrado, es la E / S del terminal full-duplex junto con la lectura anticipada. A pesar de que los programas generalmente se comunican con el usuario en términos de líneas, en lugar de caracteres individuales, la E / S del terminal full-duplex significa que el usuario puede escribir en cualquier momento, incluso si el sistema está volviendo a escribir, sin temor a perder o descifrar caracteres . Con lectura anticipada, uno no necesita esperar una respuesta a cada línea. Un buen mecanógrafo que ingresa un documento se siente increíblemente frustrado por tener que hacer una pausa antes de comenzar cada nueva línea; para cualquiera que sepa lo que quiere decir, cualquier lentitud en la respuesta se magnifica psicológicamente si la información debe ingresarse bit a bit en lugar de a toda velocidad.

[fin de la cita]

Dicho esto, hay algunos programas modernos que comen o descartan cualquier tipo de letra; sshy apt-getson dos ejemplos. Si escribe con anticipación mientras se están ejecutando, es posible que la primera parte de su entrada haya desaparecido. Eso podría ser un problema.

ssh remotehost do something that takes 20 seconds
mail bob
Dan has retired. Feel free to save any important files and then do
# ssh exits here, discarding the previous 2 lines
rm -fr *
.
Mark Plotnick
fuente
Entonces, después de bash fork()sys execel comando, ¿el primer comando todavía está conectado al STDINdel bash shell? Parece que la respuesta es no, bash parece estar amortiguando el siguiente comando. ¿Es eso correcto?
111 ---
A menos que le diga al shell que redirija el stdin del comando, el comando tendrá el mismo stdin que el shell. Todo lo que escriba se lee en el primer proceso que lo lee. El intérprete intencionalmente no intenta leer nada mientras se ejecuta un comando y espera hasta que el comando se detiene. Las cosas se vuelven más complejas si pones el comando en segundo plano con &.
Mark Plotnick
Entonces, ¿se STDINmaneja de una manera quinta? Y supongo que a menos que el proceso hijo de bash cierre explícitamente su identificador de archivo heredado STDIN, ¿ aún podría leer desde una escritura adicional?
111 ---
Sí, toda la entrada del terminal se maneja FIFO. No estoy seguro de entender tu segunda pregunta. El proceso hijo, el comando que ha invocado el shell, generalmente no cierra explícitamente su stdin; el shell se aparta y deja que el comando lea todo lo que quiera, luego el niño se detiene y el shell reanuda la lectura.
Mark Plotnick
Sí, respondiste a mis dos preguntas de seguimiento muy claramente, ¡gracias!
111 ---
12

El comportamiento básico que estás viendo es que la entrada se encuentra en un búfer en algún lugar hasta que se lee (bueno, si escribes lo suficiente, eventualmente los búferes se llenarán y se perderá algo, eso sería mucho escribir). La mayoría de las cosas ejecutadas por make no leen desde STDIN, por lo que permanece en el búfer.

El peligro es que el comando incorrecto lee su entrada. Por ejemplo, makellama a algo que decide avisarte, y luego podría leer tu próximo comando como respuesta. Cuán peligroso es eso depende del comando, por supuesto. (También pueden eliminar todas las entradas primero, simplemente descartando su entrada anterior).

Un comando, comúnmente utilizado en Makefiles, que puede hacer eso es TeX. Si encuentra un error (y no se le ha dado una marca para que nunca le pregunte al usuario), le preguntará cómo desea continuar.

Una mejor opción es, probablemente, a plazo: make && make check.

derobert
fuente
8
  1. Bueno, semi-obviamente, no debe ejecutar un segundo comando que depende del primer comando ( make, en su ejemplo) que se haya completado con éxito. Por ejemplo, make foo Enter> ./foo Enter podría causar un problema. Es posible que desee intentar acostumbrarse a escribir cosas como make && make check, donde el segundo comando se ejecutará solo si el primero tiene éxito.
  2. Es teóricamente posible que el primer comando (proceso (s)) pueda leer parte del segundo comando o eliminarlo del búfer de entrada del terminal. Si se comiera los primeros seis caracteres de make check, terminarías ejecutando el comandoheck , que probablemente no existe en su sistema (pero podría ser algo desagradable). Si el primer comando es algo benigno que usted conoce y confía, no veo ningún problema de inmediato.
  3. ¿Cómo / por qué funciona? El sistema almacena la entrada del teclado. Es un poco como el correo electrónico: puede enviar cinco mensajes a una persona en un corto período de tiempo, y se sentarán en su bandeja de entrada, esperando que los lea. Del mismo modo, mientras el primer comando no lea desde el teclado, los comandos que escriba se sentarán y esperarán a que el shell los lea. Existe un límite en cuanto a la cantidad de "escritura anticipada" que se puede almacenar, pero generalmente son varios cientos de caracteres (si no varios miles).
Scott
fuente
2
Para el punto 1, imagine que los comandos no están relacionados, es decir, lsy mountpor ejemplo. Estoy tratando de entender cómo se maneja la entrada almacenada en el búfer. Gracias por la respuesta.
111 ---