« Pseudo-terminal will not be allocated because stdin is not a terminal » : signification et solution

SSH voulait un terminal sur le serveur pour cette session, mais votre entrée est un tube, un fichier ou un script plutôt qu'un clavier : il n'en a donc pas créé. C'est un simple avis et la session continue. Pour le faire taire, utilisez -T ou indiquez la commande à exécuter. Si le programme distant a vraiment besoin d'un terminal, comme sudo qui demande un mot de passe, forcez-en un avec -tt.

Mis à jour le . Toutes les commandes ont été lancées avec OpenSSH 10.3 sur macOS face à un serveur OpenSSH 10.0 sous Linux, avec une entrée venant d'un tube, de /dev/null et d'un heredoc.

Quand il apparaît

Vous le voyez dans deux situations. Vous ne donnez aucune commande distante mais vous alimentez SSH depuis un tube ou un heredoc :

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

Ou bien vous demandez un terminal avec -t alors que votre propre entrée n'en est pas un, comme dans cron, la CI ou un script :

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

Les commandes s'exécutent quand même. Le message va sur stderr : il peut paraître alarmant dans un journal de CI, mais ce n'est pas une erreur et il ne change pas le code de sortie.

Ce que fait chaque option

Résultats obtenus en lançant tty sur le serveur avec une entrée venant de /dev/null :

CommandeTerminal sur le serveurAvis affiché
ssh server ttyNonNon
ssh -T server ttyNonNon
ssh -t server ttyNonOui
ssh -tt server ttyOuiNon

En résumé, un seul -t demande un terminal si votre côté en a un, tandis que deux le forcent malgré tout.

Solution : vous lancez un script (la plupart des cas)

Indiquez un programme pour lire le script. C'est la solution la plus propre. Elle n'affiche aucun avis, et n'affiche pas non plus le texte de bienvenue du serveur :

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

-T supprime aussi l'avis, mais le shell de connexion affiche quand même le message de bienvenue dans votre sortie :

echo uname | ssh -T user@server

Les guillemets autour de 'EOF' empêchent votre shell local de développer les variables avant l'envoi.

Pour une seule commande, passez-la directement :

ssh user@server uname

Pour les guillemets, les heredocs et les codes de retour, voir comment exécuter une commande en SSH.

Solution : le programme distant a besoin d'un terminal

Vous le reconnaîtrez à une erreur comme celle-ci, venant de 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

Des programmes comme top et vim ont des besoins similaires. Forcez un terminal :

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

Soyez prudent avec -tt dans les scripts. Avec un terminal, ce que vous envoyez est renvoyé en écho, les fins de ligne peuvent changer, et la sortie comporte des retours chariot. Un programme qui attend une touche peut aussi bloquer la tâche indéfiniment, car personne n'est là pour appuyer. Pour l'automatisation, une règle sudo étroite, sans mot de passe et sans terminal, vaut mieux que -tt. Voir sudo sur SSH.

Le définir dans votre configuration

Pour éviter de taper l'option pour un hôte utilisé par des scripts, ajoutez-la à ~/.ssh/config :

Host backup
  HostName 203.0.113.10
  RequestTTY no

Les valeurs acceptées sont no, yes, force et auto. Elles correspondent à -T, -t et -tt, auto étant la valeur par défaut.

Questions

Pseudo-terminal will not be allocated est-il une erreur ?

Non. C'est un avis sur stderr. Les commandes s'exécutent quand même et le code de sortie ne change pas.

Quelle différence entre ssh -t et ssh -tt ?

-t demande un terminal seulement si votre propre entrée en est un. -tt l'impose même depuis un pipe ou un script.

Comment masquer le message dans un script ?

Indiquez la commande, par exemple ssh user@server bash -s avec un heredoc, ou utilisez -T. RequestTTY no dans ~/.ssh/config fait de même pour un hôte.

Sources

Autres guides : Messages d'erreur

Tous les guides