In che modo bash tratta “>> ()”


9

Durante la sperimentazione del reindirizzamento dell'output e della sostituzione del processo mi sono imbattuto nel comando seguente e nel risultato risultante:

    me @ elem: ~ $ echo foo>> (gatto); barra di eco
    bar
    io @ elem: ~ $ foo

(Sì, quella nuova riga vuota alla fine è intenzionale.)

Quindi bash echo's bar, stampa il mio solito prompt, echo's foo, echo è una nuova riga e lascia il mio cursore lì. Se premo di nuovo invio, verrà stampato il mio prompt su una nuova riga e lascerà il cursore che lo segue (come previsto quando qualcuno preme invio su una riga di comando vuota).

Mi aspettavo che scrivesse foo su un descrittore di file, cat lo leggesse e il foo dell'eco, la seconda barra dell'eco dell'eco, e poi di nuovo al prompt dei comandi. Ma chiaramente non è così.

Qualcuno potrebbe spiegare cosa sta succedendo?


Vorrei suggerire di cercare le risposte su questo: unix.stackexchange.com/questions/182800/… Spiega il doppio reindirizzamento e spiega perché stai finendo con risultati diversi. Sia Muru, sia Michael Hormers.
No Time

Per una domanda che affronta esplicitamente il motivo per cui l'output della sostituzione del processo appare dopo il prompt (e in alcune circostanze non appare affatto) in alcune versioni della shell Bourne Again, consultare unix.stackexchange.com/questions/471987 .
JdeBP,

Risposte:


9

È possibile che venga foovisualizzato prima bar, dopo baro persino dopo il prompt, a seconda del momento. Aggiungi un po 'di ritardo per ottenere un tempismo coerente:

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

barappare immediatamente, quindi foodopo un secondo, quindi il prompt successivo dopo un altro secondo.

Quello che sta succedendo è che bash esegue sostituzioni di processo in background.

  1. Il processo bash principale avvia l'esecuzione di una subshell sleep 1; cate imposta una pipe su di essa.
  2. Viene eseguito il processo bash principale echo foo. Poiché ciò non riempie il buffer della pipe, il echocomando termina senza bloccarsi.
  3. Viene eseguito il processo bash principale echo bar.
  4. Il processo bash principale avvia il comando sleep 2.
  5. Nel frattempo, la subshell avvia il comando sleep 1.
  6. Dopo circa 1 secondo, sleep 1ritorna nel sottoprocesso. Il sottoprocesso procede all'esecuzione cat.
  7. cat copia il suo input nel suo output (che viene visualizzato sullo schermo) e ritorna.
  8. La subshell ha terminato il suo lavoro, esce.
  9. Dopo un altro secondo, sleep 2ritorna. Il processo principale della shell termina l'esecuzione e si arriva al prossimo prompt.

3

Non è necessario sostituire il processo per ottenere questo effetto. Prova questo:

( echo foo | cat & )

Otterrai più o meno lo stesso risultato (senza il bar; lo lascerò come esercizio) e per lo stesso motivo. In entrambi i casi, catviene avviato come attività in background. Nella mia linea qui, questo è esplicito. Nel caso della sostituzione di processo, è anche esplicito - è un processo separato associato a un descrittore di file di nomi - ma forse non è così ovvio.

Il processo figlio non termina necessariamente prima di bashstampare il prompt successivo. E poiché il suo output è bufferizzato, non emette nulla fino a quando non termina. A quel punto, bash ha appena stampato $su stderr e ora il processo in background termina dopo la stampa fooe una nuova riga.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.