J'ai configuré sudo
pour fonctionner sans mot de passe, mais quand j'essaie ssh 'sudo Foo'
, je reçois toujours le message d'erreur sudo: sorry, you must have a tty to run sudo
.
Pourquoi cela se produit-il et comment puis-je le contourner?
J'ai configuré sudo
pour fonctionner sans mot de passe, mais quand j'essaie ssh 'sudo Foo'
, je reçois toujours le message d'erreur sudo: sorry, you must have a tty to run sudo
.
Pourquoi cela se produit-il et comment puis-je le contourner?
Réponses:
C'est probablement parce que votre /etc/sudoers
fichier (ou tout fichier inclus) contient:
Defaults requiretty
... ce qui sudo
nécessite un ATS. Les systèmes Red Hat (RHEL, Fedora, etc.) nécessitent un TTY dans le sudoers
fichier par défaut . Cela ne procure aucun avantage réel en matière de sécurité et peut être supprimé en toute sécurité.
Red Hat a reconnu le problème et celui-ci sera supprimé dans les prochaines versions.
Si la modification de la configuration du serveur n’est pas une option, vous pouvez utiliser les options -t
ou -tt
pour ssh
lesquelles un pseudo-terminal est créé du côté distant, mais prenez garde qu’il comporte un certain nombre de côtés. effets.
-tt
est destiné à une utilisation interactive. Il met le terminal local en raw
mode afin que vous puissiez interagir avec le terminal distant. Cela signifie que si les ssh
E / S ne proviennent pas d'un terminal, cela aura des effets secondaires. Par exemple, toutes les entrées seront renvoyées en écho, les caractères spéciaux (terminaux ^?
, ^C
, ^U
) provoquera un traitement spécial; en sortie, LF
s sera converti en CRLF
s ... (voir la réponse à Pourquoi ce fichier binaire est-il modifié? pour plus de détails.
Pour minimiser l'impact, vous pouvez l'invoquer comme suit:
ssh -tt host 'stty raw -echo; sudo ...' < <(cat)
Le < <(cat)
évitera le réglage du terminal local ( le cas échéant) en raw
mode. Et nous utilisons stty raw -echo
pour définir la discipline de ligne du terminal distant comme passerelle (de manière à ce qu'il se comporte comme le canal qui serait utilisé à la place d'un pseudo-terminal sans -tt
, bien que cela ne s'applique qu'après l'exécution de cette commande, vous avez donc besoin de retarder l'envoi de quelque chose à l'entrée jusqu'à ce que cela se produise).
Notez que, puisque la sortie de la commande à distance ira à un terminal, cela affectera toujours sa mise en mémoire tampon (qui sera basée sur les lignes pour de nombreuses applications) et l'efficacité de la bande passante car elle TCP_NODELAY
est activée. Également avec -tt
, ssh
définit IPQoS lowdelay
par opposition à throughput
. Vous pouvez contourner les deux avec:
ssh -o IPQoS=throughput -tt host 'stty raw -echo; sudo cmd | cat' < <(cat)
Notez également que cela signifie que la commande distante ne peut pas détecter la fin de fichier sur son stdin et que les sorties stdout et stderr de la commande distante sont fusionnées dans un flux unique.
Donc, pas si bon que ça marche après tout.
Si vous avez un obtenu un moyen de frayer un pseudo-terminal sur l'hôte distant (comme avec expect
, zsh
, socat
, perl
« s IO::Pty
...), il serait alors préférable d'utiliser pour créer le pseudo-terminal pour vous connecter sudo
(mais pas pour I / O), et utiliser ssh
sans -t
.
Par exemple, avec expect
:
ssh host 'expect -c "spawn -noecho sh -c {
exec sudo cmd >&4 2>&5 <&6 4>&- 5>&- 6<&-}
exit [lindex [wait] 3]" 4>&1 5>&2 6<&0'
Ou avec script
(en supposant ici l'implémentation de util-linux
):
ssh host 'SHELL=/bin/sh script -qec "
sudo cmd <&3 >&4 2>&5 3<&- 4>&- 5>&-
" /dev/null 3<&0 4>&1 5>&2'
(en supposant (pour les deux) que le shell de connexion de l'utilisateur distant ressemble à Bourne).
Par défaut, SUDO est configuré pour exiger un TTY. C'est-à-dire que SUDO devrait être exécuté à partir d'un shell de connexion. Vous pouvez supprimer cette exigence en ajoutant le -t
commutateur à votre invocation SSH:
ssh -t someserver sudo somecommand
L' -t
affectation des forces d'un pseudo-tty.
Si vous voulez effectuer ceci globalement, modifiez /etc/sudoers
pour spécifier !requiretty
. Cela peut être fait par utilisateur, par groupe ou par niveau.
Utilisez le -t
drapeau ssh
pour forcer l'attribution de tty.
$ ssh luci tty
not a tty
$ ssh luci -t tty
/dev/ttys003
$
-t
pour forcer l'attribution quandPseudo-terminal will not be allocated because stdin is not a terminal.
J'ai rencontré ce problème avec Docker et Centos 7. J'ai finalement procédé comme suit:
yum install -y sudo
sed -i -e 's/Defaults requiretty.*/ #Defaults requiretty/g' /etc/sudoers
J'ai trouvé ce hack sur https://hub.docker.com/r/liubin/fluentd-agent/~/dockerfile
Une alternative intéressante consiste à exécuter FreeIPA ou IdM pour gérer vos utilisateurs et vos règles sudoer de manière centralisée. Vous pouvez ensuite créer des règles sudo et attribuer l'option
! requiretty
dans la règle. La commande s'exécutera comme prévu. Vous bénéficierez également de la gestion de tous les serveurs et utilisateurs à partir d’un seul ensemble de configurations.
J'ai eu le même problème. Dans mon cas, la solution était deux lignes
myscript=$(cat ssh_test.sh)
ssh -t user@host "$myscript"
Explication:
Placez les commandes que vous voulez exécuter (y compris les commandes sudo) dans un script, par exemple "ssh_test.sh".
Lisez le script en entier dans une variable appelée "myscript".
Appelez ssh avec un seul -t et fournissez la variable au lieu d'une commande.
Avant cela, je rencontrais des problèmes en utilisant des combinaisons de lecture de stdin et en utilisant heredocs
J'ai trouvé cette question en cherchant sur Google et j'ai rencontré cette erreur pour une raison complètement différente.
Mon correctif était d'arrêter d'appeler des scripts de shell en aval à sudo
partir de mon script de shell parent, alors que le script de shell parent était déjà appelé avec sudo
.
requiretty
dans sa version par défaut des sudoers. Il sera corrigé dans les nouvelles versions