¿Cómo trata bash ">> ()"

9

Mientras experimentaba con la redirección de salida y la sustitución de procesos, me topé con el siguiente comando y su salida resultante:

    yo @ elem: ~ $ echo foo>> (gato); barra de eco
    bar
    yo @ elem: ~ $ foo

(Sí, esa nueva línea vacía al final es intencional).

Así que bash echo's bar, imprime mi mensaje habitual, echo's foo, echo's a newline, y deja mi cursor allí. Si presiono enter nuevamente, imprimirá mi mensaje en una nueva línea y dejará el cursor siguiendo (como se esperaba cuando alguien presiona enter en una línea de comando vacía).

Esperaba que escribiera foo en un descriptor de archivo, cat lo lee y echo's foo, la segunda barra de echo echo, y luego vuelve al símbolo del sistema. Pero claramente ese no es el caso.

¿Podría alguien explicarme qué está pasando?

Stanley Yu
fuente
Me gustaría sugerir que busque las respuestas sobre esto: unix.stackexchange.com/questions/182800/… Explica la doble redirección y explicaría por qué está terminando con resultados diferentes. Tanto Muru como Michael Hormers.
No Time
Para una pregunta explícita sobre por qué el resultado de la sustitución del proceso aparece después de la solicitud (y en algunas circunstancias no aparece en absoluto) en algunas versiones del shell Bourne Again, consulte unix.stackexchange.com/questions/471987 .
JdeBP

Respuestas:

9

Es posible que se foomuestre antes bar, después baro incluso después de la solicitud, según el momento. Agregue un poco de retraso para obtener un tiempo constante:

$ echo foo > >(sleep 1; cat); echo bar; sleep 2 
bar
foo
$

baraparece inmediatamente, luego de fooun segundo, luego el siguiente mensaje después de otro segundo.

Lo que sucede es que bash ejecuta sustituciones de proceso en segundo plano.

  1. El proceso bash principal inicia una subshell para ejecutar sleep 1; cat, y configura una tubería hacia él.
  2. El proceso bash principal se ejecuta echo foo. Como esto no llena el búfer de la tubería, el echocomando termina sin bloqueo.
  3. El proceso bash principal se ejecuta echo bar.
  4. El proceso bash principal inicia el comando sleep 2.
  5. Mientras tanto, la subshell está iniciando el comando sleep 1.
  6. Después de aproximadamente 1 segundo, sleep 1regresa en el subproceso. El subproceso procede a ejecutarse cat.
  7. cat copia su entrada a su salida (que se muestra en la pantalla) y regresa.
  8. La subshell ha terminado su trabajo, sale.
  9. Después de otro segundo, sleep 2regresa. El proceso de shell principal termina de ejecutarse y puede ver el siguiente mensaje.
Gilles 'SO- deja de ser malvado'
fuente
3

No necesita la sustitución del proceso para obtener ese efecto. Prueba esto:

( echo foo | cat & )

Obtendrá el mismo resultado (sin el bar; lo dejaré como ejercicio) y por la misma razón. En ambos casos, catse inicia como una tarea en segundo plano. En mi línea aquí, eso es explícito. En el caso de la sustitución de procesos, también es explícito, es un proceso separado adjunto a un descriptor de archivo de nombre, pero quizás no sea tan obvio.

El proceso secundario no termina necesariamente antes de bashimprimir el siguiente mensaje. Y dado que su salida está almacenada, no genera nada hasta que finaliza. En ese momento, bash acaba de imprimir $en stderr, y ahora el proceso de fondo se cierra después de imprimir fooy una nueva línea.

rici
fuente