"Pseudo-terminal will not be allocated because stdin is not a terminal": cosa significa e come risolvere

SSH voleva un terminale sul server per questa sessione, ma il tuo input è una pipe, un file o uno script e non una tastiera, quindi non ne ha creato uno. È un avviso e la sessione continua. Per silenziarlo, usa -T oppure indica il comando da eseguire. Se il programma remoto ha davvero bisogno di un terminale, come sudo che chiede una password, forzane uno con -tt.

Aggiornata il . Tutti i comandi sono stati eseguiti con OpenSSH 10.3 su macOS contro un server OpenSSH 10.0 su Linux, con input da una pipe, da /dev/null e da un heredoc.

Quando compare

Lo vedi in due situazioni. Non dai alcun comando remoto ma alimenti SSH da una pipe o da un heredoc:

echo uname | ssh user@server
ssh user@server <<EOF
uname
EOF

Oppure chiedi un terminale con -t quando il tuo input non lo è, come in cron, in CI o in uno script:

ssh -t user@server tty < /dev/null
Pseudo-terminal will not be allocated because stdin is not a terminal.
not a tty

I comandi vengono comunque eseguiti. Il messaggio va su stderr, quindi può sembrare allarmante in un log di CI, ma non è un errore e non cambia il codice di uscita.

Cosa fa ogni opzione

Risultati dell'esecuzione di tty sul server con input da /dev/null:

ComandoTerminale sul serverAvviso stampato
ssh server ttyNoNo
ssh -T server ttyNoNo
ssh -t server ttyNoSì
ssh -tt server ttySìNo

In breve, un solo -t chiede un terminale se il tuo lato ne ha uno, mentre due lo forzano comunque.

Soluzione: stai eseguendo uno script (la maggior parte dei casi)

Indica un programma che legga lo script. È la soluzione più pulita. Non stampa alcun avviso e non mostra nemmeno il testo di benvenuto del server:

ssh user@server bash -s <<'EOF'
uname
EOF

Anche -T toglie l'avviso, ma la shell di login stampa comunque il messaggio di benvenuto nel tuo output:

echo uname | ssh -T user@server

Le virgolette intorno a 'EOF' impediscono alla tua shell locale di espandere le variabili prima dell'invio.

Per un singolo comando, passalo direttamente:

ssh user@server uname

Per virgolette, heredoc e codici di uscita, vedi come eseguire un comando via SSH.

Soluzione: il programma remoto ha bisogno di un terminale

Te ne accorgi da un errore come questo, da 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

Programmi come top e vim hanno esigenze simili. Forza un terminale:

ssh -tt user@server 'sudo systemctl restart nginx'

Fai attenzione a -tt negli script. Con un terminale, ciò che invii viene rimandato indietro come eco, i fine riga possono cambiare e l'output arriva con i ritorni a capo. Un programma che aspetta la pressione di un tasto può anche bloccare il job per sempre, perché nessuno è lì a premerlo. Per l'automazione, una regola sudo ristretta senza password e senza terminale è meglio di -tt. Vedi sudo tramite SSH.

Impostarlo nella configurazione

Per non digitare il flag per un host usato dagli script, aggiungilo a ~/.ssh/config:

Host backup
  HostName 203.0.113.10
  RequestTTY no

I valori accettati sono no, yes, force e auto. Corrispondono a -T, -t e -tt, con auto come valore predefinito.

Domande

Pseudo-terminal will not be allocated è un errore?

No. È un avviso su stderr. I comandi vengono eseguiti lo stesso e lo stato di uscita non cambia.

Che differenza c'è fra ssh -t e ssh -tt?

-t chiede un terminale solo se il tuo input è un terminale. -tt lo forza anche da una pipe o da uno script.

Come nascondo il messaggio in uno script?

Indica il comando, per esempio ssh user@server bash -s con un heredoc, oppure usa -T. RequestTTY no in ~/.ssh/config fa lo stesso per un host.

Fonti

Altro in Messaggi di errore

Tutte le guide