Est-il sûr de taper une autre commande dans STDIN pendant que la commande précédente écrit dans STDOUT?

21

Peut-être que cela a été répondu précédemment, je souhaiterais un lien vers une autre réponse ...

Si j'exécute une commande shell (dans un bashshell) comme celle-ci:

make

Ensuite, pendant que la sortie de makedéfile à partir STDOUTde la makecommande, si je tape make checket appuie enteravant que la première commande ne soit terminée, lorsque la makecommande se termine enfin, la commande suivante make checkreprendra et s'exécutera.

Ma ou mes questions sont simplement:

  1. Est-ce dangereux à faire?
  2. Existe-t-il des comportements inattendus potentiels de ce type de frappe précipitée?
  3. Pourquoi cela fonctionne-t-il ainsi?
111 ---
la source
2
1. J'espère que ce n'est pas le cas ... je fais ça depuis des années!
John WH Smith

Réponses:

20

Cela fonctionne comme il le fait car Unix est en duplex intégral. Comme l'a dit Ritchie dans The UNIX Time-sharing System: A Retrospective :

Une chose qui semble banale, mais qui fait une différence surprenante une fois qu'on y est habitué, c'est les E / S de terminal en duplex intégral avec lecture anticipée. Même si les programmes communiquent généralement avec l'utilisateur en termes de lignes, plutôt qu'en caractères uniques, les E / S de terminal en duplex intégral permettent à l'utilisateur de taper à tout moment, même si le système tape à nouveau, sans craindre de perdre ou de déformer les caractères. . Avec la lecture anticipée, il n'est pas nécessaire d'attendre une réponse à chaque ligne. Un bon dactylographe qui entre un document devient extrêmement frustré de devoir faire une pause avant de commencer chaque nouvelle ligne; pour quiconque sait ce qu'il veut dire, toute lenteur de réponse devient psychologiquement amplifiée si les informations doivent être saisies bit par bit plutôt qu'à pleine vitesse.

[fin de citation]

Cela étant dit, il existe des programmes modernes qui dévorent ou jettent tout type de frappe; sshet apt-getsont deux exemples. Si vous tapez à l'avance pendant leur exécution, vous constaterez peut-être que la première partie de votre saisie a disparu. Cela pourrait éventuellement être un problème.

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
la source
Donc, après bash fork()s et execs la commande, la première commande est-elle toujours attachée au STDINshell bash? Il semble que la réponse soit non, bash semblerait être en mémoire tampon pour la prochaine commande. Est-ce exact?
111 ---
Sauf si vous demandez au shell de rediriger le stdin de la commande, la commande aura le même stdin que le shell. Tout ce que vous tapez est lu par le premier processus qui le lit. Le shell n'essaye pas intentionnellement de lire quoi que ce soit pendant l'exécution d'une commande et attend que la commande s'arrête. Les choses deviennent plus complexes si vous mettez la commande en arrière-plan avec &.
Mark Plotnick
Est-ce donc STDINgéré d'une manière fifo? Et je suppose qu'à moins que le processus enfant de bash ne ferme explicitement son handle de fichier hérité, STDINil pourrait toujours lire à partir d'une saisie supplémentaire?
111 ---
Oui, toutes les entrées de terminal sont traitées FIFO. Je ne suis pas sûr de comprendre votre deuxième question. Le processus enfant - la commande que le shell a invoquée - ne ferme généralement pas explicitement son stdin; le shell s'éloigne et laisse la commande lire tout ce qu'il veut, puis l'enfant s'arrête et le shell reprend la lecture.
Mark Plotnick
Oui, vous avez répondu très clairement à mes deux questions de suivi, merci!
111 ---
12

Le comportement de base que vous voyez est que l'entrée se trouve quelque part dans un tampon jusqu'à ce qu'elle soit lue (eh bien, si vous tapez suffisamment, les tampons se rempliront éventuellement, et quelque chose sera perdu, ce serait beaucoup de frappe cependant). La plupart des choses exécutées par make ne lisent pas depuis STDIN, il reste donc dans le tampon.

Le danger est que la mauvaise commande lit votre entrée. Par exemple, makeappelle quelque chose qui décide de vous inviter, puis il pourrait lire votre prochaine commande comme réponse. Bien sûr, le danger dépend de la commande. (Ils peuvent également vider toutes les entrées en premier, jetant simplement votre entrée précédente.)

Une commande, couramment utilisée dans Makefiles, qui peut le faire est TeX. S'il rencontre une erreur (et n'a pas reçu d'indicateur pour ne jamais inviter l'utilisateur), il vous demandera comment vous souhaitez continuer.

Une meilleure option est probablement à exécuter: make && make check.

derobert
la source
8
  1. Eh bien, semi-évidemment, vous ne devriez pas exécuter une deuxième commande qui dépend de la makeréussite de la première commande ( , dans votre exemple). Par exemple, cela make foo Enter> ./foo Enter pourrait provoquer un problème. Vous voudrez peut-être essayer de prendre l'habitude de taper des choses comme make && make check, où la deuxième commande ne sera exécutée que si la première réussit.
  2. Il est théoriquement possible que la première commande (processus (s)) puisse lire une partie de la deuxième commande, ou sinon la supprimer du tampon d'entrée du terminal. S'il mangeait les six premiers caractères de make check, vous finiriez par exécuter la commande heck, qui n'existe probablement pas sur votre système (mais pourrait être quelque chose de méchant). Si la première commande est quelque chose de bénin que vous connaissez et en qui vous avez confiance, je ne vois immédiatement aucun problème.
  3. Comment / pourquoi ça marche? Le système met en mémoire tampon l'entrée du clavier. C'est un peu comme un e-mail: vous pouvez envoyer cinq messages à une personne en peu de temps, et ils s'asseoiront dans sa boîte de réception, attendant qu'il les lise. De même, tant que la première commande ne lit pas à partir du clavier, la ou les commandes que vous tapez s'asseoiront et attendront que le shell se déplace pour les lire. Il y a une limite quant à la quantité de «saisie anticipée» qui peut être mise en mémoire tampon, mais c'est généralement plusieurs centaines de caractères (sinon plusieurs milliers).
Scott
la source
2
Au point 1, imaginez que les commandes ne sont pas liées, c'est ls-à- dire et mountpar exemple. J'essaie de comprendre comment l'entrée en mémoire tampon est gérée. Merci d'avoir répondu.
111 ---