È sicuro digitare un altro comando in STDIN mentre il comando precedente sta scrivendo su STDOUT?


21

Forse questa è stata risposta in precedenza, accolgo con favore un link a un'altra risposta ...

Se eseguo un comando shell (in una bashshell) come il seguente:

make

Quindi, mentre l'output da makescorre dal da STDOUTdel makecomando, se scrivo make checke premo enterprima che il primo comando sia terminato, quando il makecomando termina finalmente il comando successivo make checkverrà prelevato ed eseguito.

Le mie domande sono semplicemente:

  1. È pericoloso farlo?
  2. Ci sono potenziali comportamenti imprevisti da questo tipo di digitazione urgente?
  3. Perché funziona così?

2
1. Spero di no ... lo sto facendo da anni!
John WH Smith,

Risposte:


20

Funziona come fa perché Unix è full duplex. Come ha detto Ritchie in The UNIX Time-sharing System: A Retrospective :

Una cosa che sembra banale, ma che fa una differenza sorprendente una volta che ci si è abituati, è l'I / O terminale full-duplex insieme al read-ahead. Anche se i programmi generalmente comunicano con l'utente in termini di linee, piuttosto che di singoli caratteri, l'I / O terminale full-duplex significa che l'utente può digitare in qualsiasi momento, anche se il sistema sta digitando di nuovo, senza paura di perdere o confondere i caratteri . Con read-ahead, non è necessario attendere una risposta per ogni riga. Un buon dattilografo che entra in un documento diventa incredibilmente frustrato nel dover fare una pausa prima di iniziare ogni nuova riga; per chiunque sappia cosa vuole dire qualsiasi lentezza nella risposta diventa psicologicamente ingrandita se le informazioni devono essere inserite bit per bit invece che a tutta velocità.

[fine citazione]

Detto questo, ci sono alcuni programmi moderni che divorano o scartano qualsiasi tipografo; sshe apt-getsono due esempi. Se digiti in anticipo mentre sono in esecuzione, potresti scoprire che la prima parte dell'input è scomparsa. Questo potrebbe essere potenzialmente 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 *
.

Quindi dopo bash fork()s e execs il comando, il primo comando è ancora collegato alla STDINshell bash? Sembra che la risposta sia no, bash sembrerebbe buffering per il comando successivo. È corretto?
111 ---

A meno che non si indichi alla shell di reindirizzare lo stdin del comando, il comando avrà lo stesso stdin della shell. Tutto ciò che digiti viene letto dal primo processo che lo legge. La shell non tenta intenzionalmente di leggere nulla mentre un comando è in esecuzione e attende fino all'arresto del comando. Le cose diventano più complesse se metti il ​​comando in background con &.
Mark Plotnick,

Quindi viene STDINgestito in una maniera a cinque? E suppongo che a meno che il processo figlio di bash non chiuda esplicitamente il suo handle di file ereditato, STDINallora potrebbe ancora leggere da una digitazione aggiuntiva?
111 ---

Sì, tutti gli ingressi dei terminali sono gestiti FIFO. Non sono sicuro di aver capito la tua seconda domanda. Il processo figlio - il comando di shell ha invocato - fa di solito non in modo esplicito la sua stretta stdin; la shell si fa da parte e lascia che il comando legga tutto ciò che vuole, quindi il bambino si ferma e la shell riprende a leggere.
Mark Plotnick,

Sì, hai affrontato entrambe le mie domande di follow-up in modo molto chiaro, grazie!
111 ---

12

Il comportamento di base che stai vedendo è che l'input si trova in un buffer da qualche parte fino a quando non viene letto (beh, se digiti abbastanza, alla fine i buffer si riempiranno e qualcosa andrà perso, sarebbe comunque molto da scrivere). La maggior parte delle cose eseguite da make non leggono da STDIN, quindi rimane nel buffer.

Il pericolo è che un comando errato legga il tuo contributo. Ad esempio, makechiama qualcosa che decide di richiederti e quindi potrebbe leggere il tuo prossimo comando come risposta. Quanto sia pericoloso dipende dal comando, ovviamente. (Potrebbero anche eliminare per primi tutti gli input, scartando solo quelli precedenti.)

Un comando, comunemente usato in Makefile, che può farlo è TeX. Se rileva un errore (e non è stato assegnato un flag per non richiedere all'utente), verrà richiesto come si desidera continuare.

Una soluzione migliore è probabilmente quello di eseguire: make && make check.


8
  1. Beh, semi-ovviamente, non dovresti eseguire un secondo comando che dipende dal completamento del primo comando ( make, nel tuo esempio). Ad esempio, make foo Enter> ./foo Enter potrebbe causare un problema. Potresti voler provare ad abituarti a digitare cose come make && make check, in cui il secondo comando verrà eseguito solo se il primo ha esito positivo.
  2. È teoricamente possibile che il primo comando (i processi) possa leggere parte del secondo comando o rimuoverlo in altro modo dal buffer di input del terminale. Se mangiasse i primi sei caratteri di make check, finiresti per eseguire il comando heck, che probabilmente non esiste sul tuo sistema (ma potrebbe essere qualcosa di brutto). Se il primo comando è qualcosa di benigno che conosci e di cui ti fidi, non vedo immediatamente alcun problema.
  3. Come / perché funziona? Il sistema buffer l'immissione da tastiera. È un po 'come l'e-mail: puoi inviare a una persona cinque messaggi in un breve periodo di tempo, e siederanno nella sua casella di posta in attesa che li legga. Allo stesso modo, fintanto che il primo comando non legge dalla tastiera, i comandi digitati rimarranno in attesa che la shell riesca a leggerli. Esiste un limite a quanto può essere bufferizzato il "tipo di anticipo", ma di solito sono diverse centinaia di caratteri (se non diverse migliaia).

2
Al punto 1, immagina che i comandi non siano correlati, cioè lse mountper esempio. Sto cercando di capire come viene gestito l'input buffer. Grazie per la risposta.
111 ---
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.