When it appears
You see it in two situations. You give no remote command but feed SSH from a pipe or a heredoc:
echo uname | ssh user@server
ssh user@server <<EOF
uname
EOF
Or you ask for a terminal with -t when your own input is not one, as in cron, CI or a script:
ssh -t user@server tty < /dev/null
Pseudo-terminal will not be allocated because stdin is not a terminal.
not a tty
The commands still run. The message goes to stderr, so it can look alarming in a CI log, but it is not an error and does not change the exit status.
What each option does
Results from running tty on the server with input from /dev/null:
| Command | Terminal on the server | Notice printed |
|---|---|---|
ssh server tty | No | No |
ssh -T server tty | No | No |
ssh -t server tty | No | Yes |
ssh -tt server tty | Yes | No |
In short, one -t asks for a terminal if your side has one, while two force it anyway.
Fix: you are running a script (most cases)
Name a program to read the script. This is the cleanest fix. It prints no notice, and it does not show the server's welcome text either:
ssh user@server bash -s <<'EOF'
uname
EOF
-T also removes the notice, but the login shell still prints the welcome message into your output:
echo uname | ssh -T user@server
The quotes around 'EOF' stop your local shell from expanding variables before they are sent.
For a single command, pass it directly:
ssh user@server uname
For quoting, heredocs and exit codes, see how to run a command over SSH.
Fix: the remote program needs a terminal
You will know it because of an error such as this one, from sudo:
sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
Programs like top and vim have similar needs. Force a terminal:
ssh -tt user@server 'sudo systemctl restart nginx'
Be careful with -tt in scripts. With a terminal, what you send gets echoed back, line endings can change, and output comes with carriage returns. A program waiting for a key can also hang the job forever, because nobody is there to press it. For automation, a narrow sudo rule with no password and no terminal is better than -tt. See sudo over SSH.
Set it in your config
To avoid typing the flag for a host used by scripts, add it to ~/.ssh/config:
Host backup
HostName 203.0.113.10
RequestTTY no
The accepted values are no, yes, force and auto. They match -T, -t and -tt, with auto being the default.
Questions
Is Pseudo-terminal will not be allocated an error?
No. It is a notice on stderr. The commands still run and the exit status does not change.
What is the difference between ssh -t and ssh -tt?
-t asks for a terminal only if your own input is one. -tt forces a terminal even from a pipe or a script.
How do I hide the message in a script?
Name the command, for example ssh user@server bash -s with a heredoc, or use -T. RequestTTY no in ~/.ssh/config does the same for one host.