Chapter 16 ■ telnet and SSh
296
A terminal is a device into which a user types text and on whose screen the computer’s response can be
displayed. If a Unix machine has physical serial ports that can host a physical terminal, then the device directory
will contain entries such as /dev/ttyS1 with which programs can send and receive strings to that device. However,
most terminals these days are, in reality, other programs: an xterm terminal, a Gnome or KDE terminal program, the
Mac OS X iTerm or Terminal, or even a PuTTY client on a Windows machine that has connected via a remote-shell
protocol of the kind discussed in this chapter.
Programs running inside a terminal on your computer will often try to autodetect whether they are talking to a
person, and only if they are connected to a terminal device will they assume that their output should be formatted for
humans. Therefore, the Unix operating system provides a set of “pseudo-terminal” devices (which might have less
confusingly been named “virtual” terminals) with names like /dev/tty42 to which processes can be connected if
you want them to be convinced that they are communicating with a real person. When someone brings up an xterm
or connects through SSH, the xterm or SSH daemon grabs a fresh pseudo-terminal, configures it, and runs the user’s
shell attached to it. The shell examines its standard input, sees that it is a terminal, and presents a prompt since it
believes that it is talking to a person.
■ Note Because the noisy teletype machine was the earliest example of a computer terminal, Unix often uses ttY as
the abbreviation for a terminal device. that is why the call to test whether your input is a terminal is named isatty().
This is a crucial distinction to understand: the shell presents a prompt because, and only because, it thinks it is
connected to a terminal. If you start up a shell and give it a standard input that is not a terminal—like, say, a pipe from
another command—then no prompt will be printed, but it will still respond to commands.
$ cat | bash
echo Here we are inside of bash, with no prompt
Here we are inside of bash, with no prompt
python3
print('Python has not printed a prompt, either.')
import sys
print('Is this a terminal?', sys.stdin.isatty())
Not only has bash not printed a prompt, neither has Python. In fact, Python is being unusually quiet. While
bash at least responded to our echo command with a line of text, at this point you have typed three lines of input into
Python without seeing any response. What is going on?
The answer is that since its input is not a terminal, Python thinks that it should just blindly read an entire Python
script from standard input. After all, its input is a file, and files have whole scripts inside. To complete this potentially
endless read-until-end-of-file that Python is performing, you will have to press Ctrl-D to send an “end-of-file” to cat,
which will then close its own output and let the example finish.
Once you have closed its input, Python will interpret and run the three-line script you have provided (everything
past the word python in the session just shown), and you will see the results on your terminal followed by the prompt
of the shell that you started at.
Python has not printed a prompt, either.
Is this a terminal? False
Some programs auto-adjust their output format depending on whether they are talking to a terminal. The ps
command will truncate each output line to your terminal width if used interactively but produce arbitrarily wide
output if its output is a pipe or file. Also, the familiar column-based output of the ls command gets replaced with a file
name on each line (which is, you must admit, an easier format for reading by another program).