The "stdin is not a tty" message appears when SSH runs a command without allocating a terminal, typically with piped input or remote scripts. Force a TTY with the -t flag when one is genuinely needed.
This message means SSH detected that standard input (stdin) is not connected to a terminal device, so it did not allocate a pseudo-terminal (PTY) for the remote session. It usually appears as a warning when you run a command over SSH with redirected input (a pipe, file, or here-document) or when a remote shell startup script tries to do something that only makes sense in an interactive terminal. In most cases the command still executes correctly and the message is harmless; it only becomes a real problem when a remote program genuinely requires a TTY (for example, an interactive prompt or a tool that calls `tcgetattr`).
The message is often just a harmless warning. If your remote command runs fine and produces correct output, you can ignore it. Only force a TTY when a remote program genuinely needs one (interactive prompts, top, editors, tools that call tcgetattr).
To silence the warning for a non-interactive command without allocating a TTY, you can explicitly disable PTY allocation:
ssh -T user@host 'your-command'When a remote command truly requires an interactive terminal, force pseudo-terminal allocation with -t:
ssh -t user@host 'your-command'If SSH itself has no local TTY (for example, you are already inside a pipe or a script), a single -t is not enough. Use -tt to force allocation regardless of the local stdin state:
ssh -tt user@host 'interactive-command'When piping a local script to a remote shell, name the interpreter explicitly so there is no ambiguity, and do NOT force a TTY (a PTY would merge stdout/stderr and echo input, corrupting script output):
ssh user@host 'bash -s' < /path/to/local_script.shThis streams the local file into the remote bash over stdin and runs without a terminal, which is exactly what a non-interactive script wants. Reserve -t/-tt for scripts that must drive an interactive program.
If .bashrc or .profile runs a command that needs a terminal (like mesg y or stty), wrap it in a TTY check so it only runs in interactive sessions:
# Original (prints "stdin: is not a tty" in non-interactive SSH)
mesg y
# Fixed (only runs when stdin is a terminal)
if [ -t 0 ]; then
mesg y
fiThis lets your startup files work in both interactive and non-interactive SSH sessions. This is the single most common real fix when the warning appears on every non-interactive connection.
When you pipe data into a remote command, specify a command that consumes stdin and leave the TTY off. Forcing -t here is wrong: with a PTY, the remote stdin becomes the terminal rather than your pipe, so the piped data may not reach the command.
# Triggers the warning (implicit command + redirected stdin)
echo 'data' | ssh user@host
# Correct: name a command that reads stdin (no -t)
echo 'data' | ssh user@host 'cat > /tmp/file.txt'Do NOT try to feed a sudo password this way. A command like echo 'password' | ssh -t user@host 'sudo -S cmd' does not work (with -t the pipe is no longer the remote stdin) and exposes the password in your shell history and process list. Instead, configure passwordless privilege for the specific command on the remote host with a tightly scoped sudoers rule:
# On the remote host, e.g. /etc/sudoers.d/deploy (edit via 'sudo visudo -f')
deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart myappThen run it over SSH with no password and no TTY:
ssh user@host 'sudo systemctl restart myapp'If an interactive password prompt is genuinely required, run ssh -t user@host 'sudo cmd' and type the password at the prompt rather than piping it.
In automation, this warning around Git usually means the SSH key is not loaded, not that a TTY is missing. Configure the agent and a non-interactive host-key policy instead of forcing a terminal:
# Start the agent and load the deploy key
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
# Avoid the interactive host-key prompt safely by pinning the key
ssh-keyscan github.com >> ~/.ssh/known_hostsGit invokes ssh itself and does not need a TTY for git clone/fetch/push, so adding -t is unnecessary and can break the transport. Pinning the host key with ssh-keyscan is preferred over StrictHostKeyChecking=no, which disables host verification.
Understanding TTY allocation: A TTY (teletypewriter) is a terminal interface for interactive communication. By default ssh allocates a pseudo-terminal (PTY) only when its own stdin is a terminal. When stdin is redirected (a pipe, file, or here-document), SSH skips PTY allocation because the session is non-interactive.
The -t, -tt, and -T flags: -t requests a PTY but is suppressed when SSH has no local TTY; -tt forces a PTY regardless of local stdin; -T explicitly disables PTY allocation, which is the right choice for non-interactive commands and for silencing the warning. Note that a forced PTY combines stdout and stderr into one stream and echoes input, so avoid it for commands whose output you parse.
Why piping into a PTY fails: When a PTY is allocated, the remote command's stdin is the terminal, not your pipe. That is why constructs like echo x | ssh -t host 'cmd' do not deliver x to cmd. Drop -t for piped data, or use a non-interactive design (sudoers NOPASSWD, key-based auth) instead of piping secrets.
Distro and management-panel differences: The warning frequently traces back to startup scripts injected by management panels (such as cPanel) or default /etc/profile.d snippets on RHEL/CentOS that call mesg/stty. The if [ -t 0 ] guard is the durable fix.
Containers and rootless contexts: In Docker/Kubernetes exec, TTY behavior is controlled by explicit flags (docker exec -it, kubectl exec -it); the equivalent of -t must be requested deliberately because there is no attached terminal by default.
sign_and_send_pubkey: no mutual signature supported
How to fix "sign_and_send_pubkey: no mutual signature supported" in SSH
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
How to fix SSH man-in-the-middle attack warning in SSH
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
How to fix "WARNING: UNPROTECTED PRIVATE KEY FILE!" in SSH
sign_and_send_pubkey: signing failed for RSA from agent: agent refused operation
How to fix "sign_and_send_pubkey: signing failed for RSA from agent: agent refused operation" in SSH
Bad owner or permissions on /home/user/.ssh/known_hosts
How to fix "Bad owner or permissions on known_hosts" in SSH