According to my knowledge, /dev/pts files are created for ssh or telnet sessions.

  • 6
    echo Hello > /dev/pts/1 ... See what happens, it's your terminal. – Sepahrad Salour Oct 4 '13 at 7:39
  • 6
  • 1
    @SepahradSalour one has to adapt the pts number to its context. my sshd has used /dev/pts/30 for my session. – Gab是好人 Jan 26 '17 at 13:05
  • 2
    @Gab是好人 To get the location of your current terminal, you can use the command tty. – jeromej Feb 16 '17 at 15:36

Nothing is stored in /dev/pts. This filesystem lives purely in memory.

Entries in /dev/pts are pseudo-terminals (pty for short). Unix kernels have a generic notion of terminals. A terminal provides a way for applications to display output and to receive input through a terminal device. A process may have a controlling terminal — for a text mode application, this is how it interacts with the user.

Terminals can be either hardware terminals (“tty”, short for “teletype”) or pseudo-terminals (“pty”). Hardware terminals are connected over some interface such as a serial port (ttyS0, …) or USB (ttyUSB0, …) or over a PC screen and keyboard (tty1, …). Pseudo-terminals are provided by a terminal emulator, which is an application. Some types of pseudo-terminals are:

  • GUI applications such as xterm, gnome-terminal, konsole, … transform keyboard and mouse events into text input and display output graphically in some font.
  • Multiplexer applications such as screen and tmux relay input and output from and to another terminal, to decouple text mode applications from the actual terminal.
  • Remote shell applications such as sshd, telnetd, rlogind, … relay input and output between a remote terminal on the client and a pty on the server.

If a program opens a terminal for writing, the output from that program appears on the terminal. It is common to have several programs outputting to a terminal at the same time, though this can be confusing at times as there is no way to tell which part of the output came from which program. Background processes that try to write to their controlling terminal may be automatically suspended by a SIGTTOU signal.

If a program opens a terminal for reading, the input from the user is passed to that program. If multiple programs are reading from the same terminal, each character is routed independently to one of the programs; this is not recommended. Normally there is only a single program actively reading from the terminal at a given time; programs that try to read from their controlling terminal while they are not in the foreground are automatically suspended by a SIGTTIN signal.

To experiment, run tty in a terminal to see what the terminal device is. Let's say it's /dev/pts/42. In a shell in another terminal, run echo hello >/dev/pts/42: the string hello will be displayed on the other terminal. Now run cat /dev/pts/42 and type in the other terminal. To kill that cat command (which will make the other terminal hard to use), press Ctrl+C.

Writing to another terminal is occasionally useful to display a notification; for example the write command does that. Reading from another terminal is not normally done.

| improve this answer | |
  • Either I'm misunderstanding what you're trying to say, or your information is off. Backgrounded processes writing to the terminal will not result in a SIGTTIN. Nor can multiple programs read from the terminal at the same time (your statement that "each character is routed independently"). Only one program can read from the terminal at any time, and an attempt by a backgrounded program to read from that terminal will result in a SIGTTIN. That is the only case where SIGTTIN is automatically sent. – Patrick Oct 5 '13 at 5:14
  • Also you cannot read from another terminal either. To do so would be a significant security vulnerability as you would be able to intercept data. You can strace the program reading input, but that is it. – Patrick Oct 5 '13 at 5:20
  • 5
    @Patrick Background processes writing to the terminal get SIGTTOU, that was a typo. Multiple programs can read from the terminal at the same time (try it and see, the way I describe in the next paragraph; you have to do it from a process whose controlling terminal is not that terminal). Yes, you can read from another terminal, as long as it belongs to you — why do you think that would be impossible? – Gilles 'SO- stop being evil' Oct 5 '13 at 11:09
  • Background processes writing to the terminal only get SIGTTOU if the tostop tty flag is set. This flag is not set by default. And I stand corrected on the read from anoter TTY. I tried it and it does work, but it's on a per-read basis, not a per-character basis (when sitting at a shell prompt they are the same as shells read 1 character at a time). It might be good to clarify this point as that's now how I interpreted your answer. – Patrick Oct 5 '13 at 16:05
  • 2
    @Patrick Sure, a read call will only return consecutive characters (or rather bytes, I should say), but the application has no control over how many bytes a read call will return, so it's no better. – Gilles 'SO- stop being evil' Oct 6 '13 at 18:13

The files in /dev/pts are "pseudo-ttys". They're like named pipes to an extent, but they also imitate old serial-connection terminals, like VT-100s. Pseudo-ttys do the work of transferring bytes from keyboard to program, and from program to output device, which sounds simple. But that answers your explicity question: the kernel stores nothing in /dev/pts/0 for example. Only streams of bytes from stdout of a program connected to the pseudo-tty goes in, and programs whose stdin is connected to the same pseudo-tty read those bytes.

Pseudo-ttys also put a layer of indirection into those streams of bytes. The kernel can inspect bytes for special values like "Control-C" or "Control-D" or "Control-U" (which are all configurable, see man stty) and send a SIGINT, set end-of-file on stdin, or erase a line on the input. There's also a buffering function in there somewhere, so my "stores nothing" is somewhat wrong, but only by a few kilobytes.

The kernel can inspect byte values on output and do things like turn a newline (ASCII linefeed, LF or "\n") into two bytes, carriage-return and linefeed (CRLF or "\r\n"), or whatever bytes a serial terminal hardware requires. The indirection of a pseudo-tty allows independence from hardware.

Pseudo-ttys also allow all the "set baud rate", "set parity" and so forth ioctl() system calls, and probably do nothing with them. This lets programs that were written back in the day of VT-100s, ADM-3 and Wyse whatevers keep working without erroring out. Software, the pseudo-ttys device driver, acts like hardware.

Pseudo-ttys may be used by sshd and telnet, but they're also used between a terminal emulator (like xterm or rxvt) and the shell that typically runs inside the xterm.

Linux and a lot of Unixes have pseudo-ttys. Plan 9 does not. Pseudo-ttys are a little bit of a relic, left over from the days of serial-cable connected hardware terminals.

| improve this answer | |

/dev/ is a special directory for device files. These are abstractions, they are not real files on disk. The directory is populated at boot and subject to change to reflect existing device interfaces, which are created and destroyed by the kernel and a userspace daemon, udevd.

Many of the devices so represented are virtual. This includes the entries in /dev/pts, which are console devices. This is why one is created for remote sessions; they are also created when you open a local GUI terminal.

You can open them as files, although it's not of much use value. To get the /dev/pts node your shell is connected, use tty:

> tty

Now switch to some other console and try:

> echo "duck!" > /dev/pts/4

Clever. Now try:

> cat /dev/pts/4

Then try and use the shell at /dev/pts/4. You're stuck until you exit the cat on the other side, but most of what you type on pts/4 will pass through (e.g. trying "hello world" I ended up with hl on pts/4 and ello word on the cat console).

My guess here is that the device is taking input from the shell, and outputting it via the system, which is how stuff ends up on the screen -- the shell isn't dealing with hardware, the system is. Try strace bash (and have a look at man strace if you don't know what it is); you get a preliminary flurry of calls as bash starts up. Now start hitting keys:

read(0, "h", 1)                         = 1
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "h", 1h)                        = 1
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
read(0, "e", 1)                         = 1
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "e", 1e)                        = 1
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
read(0, "y", 1)                         = 1
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "y", 1y)                        = 1
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0

For every letter typed there's a read from standard input and a write to standard out. But what's the shell's standard out connected to? Now try strace on your GUI terminal -- you'll have to figure out the name if you don't know it, e.g. on KDE it's konsole, and GNOME has the gnome-terminal, I believe. The output from that strace is probably more cryptic -- mine has a lot of poll() and recvfrom(). I don't see any writes, but if you now pull the cat trick from another terminal, you'll notice when you type, the key strokes that get read by cat cause no response at all in the strace output -- the terminal isn't recieving them. So the GUI terminal app and cat are competing to read from the same device, which the shell is outputing into.

| improve this answer | |
  • what is the use of 'cat /dev/pts/4' when we are stuck and why we are stucking while executing this command . – user2720323 Oct 4 '13 at 8:14
  • I added a few paragraphs to try and explain this. – goldilocks Oct 4 '13 at 9:18

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