21

Perhaps this has been answered previously, I would welcome a link to another answer...

If I execute a shell command (in a bash shell) like the following:

make

Then while the output from make is scrolling by from the STDOUT of the make command, if I type make check and press enter before the first command is finished executing, when the make command finally finishes the next command make check will pick right up and run.

My question(s) are simply:

  1. Is this dangerous to do?
  2. Are there any potential unexpected behaviors from this kind of rush typing?
  3. Why does this work the way it does?
1
  • 2
    1. I hope it's not... I've been doing this for years! Jan 13 '15 at 20:59
20

It works the way it does because Unix is full-duplex. As Ritchie said in The UNIX Time-sharing System: A Retrospective:

One thing that seems trivial, yet makes a surprising difference once one is used to it, is full-duplex terminal I/O together with read-ahead. Even though programs generally communicate with the user in terms of lines, rather than single characters, full-duplex terminal I/O means that the user can type at any time, even if the system is typing back, without fear of losing or garbling characters. With read-ahead, one need not wait for a response to every line. A good typist entering a document becomes incredibly frustrated at having to pause before starting each new line; for anyone who knows what he wants to say any slowness in response becomes psychologically magnified if the information must be entered bit-by-bit instead of at full speed.

[end quote]

That being said, there are some modern programs that eat up or discard any typeahead; ssh and apt-get are two examples. If you type ahead while they're running, you may find that the first part of your input has disappeared. That could conceivably be a problem.

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 *
.
5
  • So after bash fork()s and execs the command, is the first command still attached to the STDIN of the bash shell? It sounds like the answer is no, bash would seem to be buffering for the next command. Is that correct?
    – 111---
    Jan 13 '15 at 22:20
  • Unless you tell the shell to redirect the stdin of the command, the command will have the same stdin as the shell. Anything you type is read by the first process that reads it. The shell intentionally does not try to read anything while a command is running, and waits until the command stops. Things get more complex if you put the command in the background with &. Jan 13 '15 at 22:26
  • So is STDIN handled in a fifo manner? And i suppose that unless the child process of bash explicitly closes its inherited file handle to STDIN then it could still read from additional typing?
    – 111---
    Jan 13 '15 at 23:11
  • Yes, all terminal input is handled FIFO. Not sure I understand your second question. The child process - the command the shell has invoked - usually does not explicitly close its stdin; the shell steps out of the way and lets the command read all it wants, then the child stops and the shell resumes reading. Jan 14 '15 at 0:17
  • Yeah you addressed both of my follow up questions very clearly, thanks!
    – 111---
    Jan 14 '15 at 13:28
12

The basic behavior you're seeing is that input sits in a buffer somewhere until it's read (well, if you type enough, eventually the buffers will fill up, and something will be lost, that'd be a lot of typing though). Most things run by make do not read from STDIN, so it stays in the buffer.

The danger is that the wrong command reads your input. E.g., make calls something that decides to prompt you, and then it might read your next command as an answer. How dangerous that is depends on the command, of course. (They may also flush all input first, just discarding your previous input.)

One command, commonly used in Makefiles, that may do that is TeX. If it encounters an error (and hasn't been given a flag to never prompt the user), it'll prompt how you want to continue.

A better option is probably to run: make && make check.

0
8
  1. Well, semi-obviously, you shouldn't run a second command that depends on the first command (make, in your example) having completed successfully.  For example, make foo Enter> ./foo Enter could cause a problem.  You might want to try to get into the habit of typing things like make && make check, where the second command will be executed only if the first one succeeds.
  2. It is theoretically possible that the first command (process(es)) could read part of the second command, or otherwise remove it from the terminal input buffer.  If it ate the first six characters of make check, you would end up executing the command heck, which probably doesn't exist on your system (but might be something nasty).  If the first command is something benign that you know and trust, I don't immediately see any problem.
  3. How/why does it work?  The system buffers keyboard input.  It’s a little like e-mail: you can send a person five messages in a short period of time, and they will sit in his Inbox, waiting for him to read them.  Similarly, as long as the first command is not reading from the keyboard, the command(s) that you type will sit and wait for the shell to get around to reading them.  There is a limit as to how much “type-ahead” can be buffered, but it’s commonly several hundred characters (if not several thousand).
1
  • 2
    To point 1, imagine that the commands are unrelated, i.e. ls and mount for example. I am trying to understand how the buffered input is handled. Thanks for the answer.
    – 111---
    Jan 13 '15 at 22:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.