J'ai configuré sudo
pour fonctionner sans mot de passe, mais quand j'essaie de 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 contourner ce problème ?
Réponse acceptée :
C'est probablement parce que votre /etc/sudoers
fichier (ou tout fichier qu'il inclut) a :
Defaults requiretty
…ce qui rend sudo
besoin d'un ATS. Les systèmes Red Hat (RHEL, Fedora…) sont connus pour exiger un TTY dans les sudoers
par défaut dossier. Cela n'offre 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 il sera supprimé dans les prochaines versions.
Si la modification de la configuration du serveur n'est pas une option, pour contourner cette mauvaise configuration, vous pouvez utiliser le -t
ou -tt
options pour ssh
qui génère un pseudo-terminal du côté distant, mais attention, cela a un certain nombre d'effets secondaires.
-tt
est destiné à une utilisation interactive. Il met le terminal local en raw
mode afin que vous interagissiez avec le terminal distant. Cela signifie que si ssh
Les E/S ne sont pas de/vers un terminal, cela aura des effets secondaires. Par exemple, toutes les entrées seront renvoyées en écho, les caractères terminaux spéciaux (^?
, ^C
, ^U
) entraînera un traitement spécial ; en sortie, LF
s seront convertis en CRLF
s… (voir cette réponse à Pourquoi ce fichier binaire est-il modifié ? pour plus de détails.
Pour minimiser l'impact, vous pouvez l'invoquer comme :
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 pass through (en fait, il se comporte comme le tube 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 devez donc retarder l'envoi de quelque chose pour 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 la ligne pour de nombreuses applications) et l'efficacité de la bande passante depuis TCP_NODELAY
est sur. Aussi avec -tt
, ssh
définit l'IPQoS sur lowdelay
par opposition au 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 à distance ne peut pas détecter la fin de fichier sur son stdin et que stdout et stderr de la commande à distance sont fusionnés en un seul flux.
En relation :Debian – Supprimer l'utilisateur et le mot de passe lors de la connexion dans Debian 9 Stretch ?Donc, pas si bon que ça après tout.
Si vous avez un moyen de générer un pseudo-terminal sur l'hôte distant (comme avec expect
, zsh
, socat
, perl
IO::Pty
…), alors il vaudrait mieux l'utiliser pour créer le pseudo-terminal pour attacher sudo
à (mais pas pour les E/S), et utilisez 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
(ici en supposant 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 est de type Bourne).