Every once in a while I will do something like
ssh user@host sudo thing
and I am reminded that ssh doesn't allocate a pseudo-tty by default. Why doesn't it? What benefits would I be losing if I aliased ssh
to ssh -t
?
Every once in a while I will do something like
ssh user@host sudo thing
and I am reminded that ssh doesn't allocate a pseudo-tty by default. Why doesn't it? What benefits would I be losing if I aliased ssh
to ssh -t
?
The primary difference is the concept of interactivity. It's similar to running commands locally inside of a script, vs. typing them out yourself. It's different in that a remote command must choose a default, and non-interactive is safest. (and usually most honest)
STDIN
Ctrl-c
break would normally cause a loop on the ssh command to break immediately, your control sequences will instead be sent to the remote server. This results in a need to "hammer" the keystroke to ensure that it arrives when control leaves the ssh command, but before the next ssh command begins.I would caution against using
ssh -t
in unattended scripts, such as crons. A non-interactive shell asking a remote command to behave interactively for input is asking for all kinds of trouble.You can also test for the presence of a terminal in your own shell scripts. To test STDIN with newer versions of bash:
STDOUT
ssh
tossh -t
, you can expect to get an extra carriage return in your line ends. It may not be visible to you, but it's there; it will show up as^M
when piped tocat -e
. You must then expend the additional effort of ensuring that this control code does not get assigned to your variables, particularly if you're going to insert that output into a database.Here is the same bash test as earlier, but for STDOUT:
While it's possible to work around these issues, you're inevitably going to forget to design scripts around them. All of us do at some point. Your team members may also not realize/remember that this alias is in place, which will in turn create problems for you when they write scripts that use your alias.
Aliasing
ssh
tossh -t
is very much a case where you'll be violating the design principle of least surprise; people will be encountering problems they do not expect and may not understand what is causing them.SSH escape/control characters and transfer of binary files
One advantage that hasn’t been mentioned in the other answers is that when operating without a pseudo-terminal, the SSH escape characters such as
~C
are not supported; this makes it safe for programs to transfer binary files which may contain these and other control characters.Without a pseudo-terminal the characters are transferred to the remote host “as is”:
If you try to forcing the allocation of a pseudo-terminal, the inclusion of the
~C
causes thessh>
prompt to be printed to allow the user to enter an SSH command, interrupting the transfer.A
~.
sequence is worse as it results in no data being transferred:Software flow control
Software flow control characters (XON/XOFF) may also be treated specially when a pseudo-terminal is allocated.
With a pseudo-terminal, the
Ctrl-S
character is interpreted as a signal to pause the input stream so no more data can be sent after this character is encountered (unless it’s followed by aCtrl-Q
character later in the input stream).In this case, forcing the allocation of a pseudo-terminal results in the file on the remote end being empty.
In this case, forcing the allocation of a pseudo-terminal results in the file on the remote end containing all three lines but without the control characters:
Conversion of line-ending characters
With a pseudo-terminal, Line Feed characters (decimal 10, hex
0A
in ASCII) are also translated toCRLF
sequences (hex0D0A
in ASCII) .From the previous example:
Copy a binary file using a pseudo-terminal
Copy a binary file without using a pseudo-terminal:
The two files aren’t the same:
The one which was copied with a pseudo-terminal is corrupted:
while the other isn’t:
Transferring files over SSH
This is particularly important for programs such as
scp
orrsync
which use SSH for data transfer. This detailed description of how the SCP protocol works explains how the SCP protocol consists of a mixture of textual protocol messages and binary file data.OpenSSH helps protects you from yourself
It’s worth noting that even if the
-t
flag is used, the OpenSSHssh
client will refuse to allocate a pseudo-terminal if it detects that itsstdin
stream is not a terminal:You can still force the OpenSSH client to allocate a pseudo-terminal with
-tt
:In either case, it (sensibly) doesn’t care if
stdout
orstderr
are redirected:On remote host we have to do with this setting:
Without sudo
And with sudo
With sudo we get the extra carriage return
The solution is to disable the translate newline to carriage return-newline with
stty -onlcr
Think about backward-compatibility.
The 2 primary modes of ssh are interactive-login with a pty, and specified-command without a pty, because those were the exact capabilities of
rlogin
andrsh
respectively. ssh needed to provide a superset ofrlogin
/rsh
features to be successful as a replacement.So the defaults were decided before ssh was born. Combinations like "I wanna specify a command and get a pty" had to be accessed with new options. Be glad that at least we have that option now, unlike when we were using
rsh
. We didn't trade away any useful features to get encrypted connections. We got bonus features!From
man ssh
:This allows you to get a "shell" of sorts to the remote server. For servers that do not grant shell access but allow SSH (i.e, Github is a known example for SFTP access), using this flag will cause the server to reject your connection.
The shell also has all your environmental variables (like
$PATH
) so executing scripts generally needs a tty to work.