11

The normal way to connect to an SSH server is ssh username@ip_address. But a user may only want to run a program on the remote machine. So the program name follows after the normal argument which is ssh username@ip_address <program_name>. For example, ssh username@ip_address ls. That argument is fine except for interactive programs (that also accept user input as well as providing output) e.g. top. The output is

TERM environment variable not set.

which means no (pseudo-)terminal is attached between the sshd and top programs. The solution is to add argument -t where the whole command now becomes ssh -t username@ip_address top.

My question is why can't sshd by default also use a pseudo-terminal to communicate with non-interactive programs so there is no need to add the -t argument for interactive programs?

  • 3
    The short answer is "because that's usually not what you want". – Celada Mar 13 '16 at 9:42
  • I predict your question will get moderated for essentially begging an opinion/making a gripe. But Let's flip the question around: why should ssh allocate tty resources when it's not required in a vast majority of cases? The REAL question is: why isn't force-tty allocation a config option so you can make it a default or host-specific default? – Otheus Mar 13 '16 at 9:45
  • @Otheus It is config option. You can set RequestTTY yes (or force) in your config. – Jakuje Mar 13 '16 at 9:52
  • Er indeed. Seems to have been introduced in 6 but buggy until shortly after. I only use very old distributions. :) – Otheus Mar 13 '16 at 9:56
  • 6
    How can SSH reliably know that a program is interactive? Even top can run in batch mode. – muru Mar 13 '16 at 15:50
18

It's true that, as others have said, PTYs have a certain overhead - but the big reason for not using a PTY when running a remote command is that you lose information.

Normally, when you run a command remotely via ssh, the command's stdout and stderr streams are sent to the local stdout and stderr, which means you can redirect/pipe them separately - for example:

$ ssh server ls foo bar
ls: cannot access bar: No such file or directory
foo
$ ssh server ls foo bar > stdout 2> stderr
$ cat stdout
foo
$ cat stderr
ls: cannot access bar: No such file or directory

But if you use a PTY, all output goes to stdout, because PTYs don't have separate streams for output/error:

$ ssh -t server ls foo bar > stdout 2> stderr
$ cat stdout
ls: cannot access bar: No such file or directory
foo
$ cat stderr
$
  • This is a good point I was not aware of. – Jakuje Mar 13 '16 at 13:38
  • 1
    @ThomasDickey: Hardly... the question is not "what is the historical reason behind the developers' choice of this default", but "why can't sshd use a pseudo-terminal by default" (the emphasis is mine, but the wording is more or less direct from the question). So the difference in behaviour (which would break a number of scripting idioms) is relevant, independent of how the developers made that choice :-) – psmears Mar 13 '16 at 13:40
  • 2
    @ThomasDickey: Have you even read the question? Where does it mention the opinion of the developers? – psmears Mar 13 '16 at 13:47
  • 1
    +1 points out a specific advantage of not using a pty (other than performance). You could still argue that -t should be the default, and an option required to turn it off, so really the minor performance advantage is what makes most sense to me for cases where it doesn't matter. – Peter Cordes Mar 13 '16 at 19:51
7

Manual page for ssh describes this:

When the user's identity has been accepted by the server, the server either executes the given command in a non-interactive session or, if no command has been specified, logs into the machine and gives the user a normal shell as an interactive session. All communication with the remote command or shell will be automatically encrypted.

It is feature and probably caused by historical reasons of rsh behaviour. It is pretty reasonable. Most of the commands are really not interactive and it is not free operation to allocate PTY (which was more important 20 years back).

1

How is ssh suppose to tell if the command you are invoking is interactive or not?

This nightmare is made worse when you realize you could be logging into a machine running a non-unix OS.

There being no easy solution one case had to be the default.

  • It does not know. It can't know. And therefore we have manual page which describes behaviour in these situations. – Jakuje Mar 13 '16 at 21:03

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.