As most of you have done many times, it's convenient to view long text using less
:
some_command | less
Now its stdin is connected to a pipe (FIFO). How can it still read commands like up/down/quit?
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
Sign up to join this communityAs mentioned by William Pursell, less
reads the user’s keystrokes from the terminal. It explicitly opens /dev/tty
, the controlling terminal; that gives it a file descriptor, separate from standard input, from which it can read the user’s interactive input. It can simultaneously read data to display from its standard input if necessary. (It could also write directly to the terminal if necessary.)
You can see this happen by running
some_command | strace -o less.trace -e open,read,write less
Move around the input, exit less
, and look at the contents of less.trace
: you’ll see it open /dev/tty
, and read from both file descriptor 0 and whichever one was returned when it opened /dev/tty
(likely 3).
This is common practice for programs wishing to ensure they’re reading from and writing to the terminal. One example is SSH, e.g. when it asks for a password or passphrase.
As explained by schily, if /dev/tty
can’t be opened, less
will read from its standard error (file descriptor 2). less
’s use of /dev/tty
was introduced in version 177, released on April 2, 1991.
If you try running cat /dev/tty | less
, as suggested by Hagen von Eitzen, less
will succeed in opening /dev/tty
but won’t get any input from it until cat
closes it. So you’ll see the screen blank, and nothing else until you press CtrlC to kill cat
(or kill it in some other way); then less
will show whatever you typed while cat
was running, and allow you to control it.
cat blah |
can be replaced by < blah
, and even that’s unnecessary in this case since less blah
works too (well, less -f /dev/tty
). But reading from /dev/tty
is a bit of a special case, and all three variants (cat /dev/tty | less
, less < /dev/tty
and less -f /dev/tty
) produce different results.
Jun 30, 2018 at 16:51
/dev/tty
and /dev/pts/...
.
Jul 1, 2018 at 12:11
UNIX gives two methods to read users input while stdin has been redirected:
The original method is to read from stderr. Stderr is open for writing and reading and this is still mentioned in POSIX.
Later UNIX versions did (around 1979) add a /dev/tty
driver interface that allows to open the controlling tty of a process. Since there are processes without a controlling tty, it is possible that an attempt to open /dev/tty
fails. Friendly written software therefore has a fallback to the original method and then tries to read from stderr.
dup()
licates of the same file description, though, all opened on the tty. (Apparently POSIX still requires or suggest (this answer doesn't say) that stderr be a read/write FD, not opened with something like open("/dev/ttyS0", O_WRONLY)
. Reading stderr would fail in that case.)
Jul 2, 2018 at 8:41
less
reads the data to display from stdin, and it reads commands from the tty. They are different things.less
reads data from stdin, and commands from the tty.