Ho configurato sudo
per eseguire senza una password, ma quando provo a ssh 'sudo Foo'
, ricevo ancora il messaggio di errore sudo: sorry, you must have a tty to run sudo
.
Perché succede e come posso aggirarlo?
Risposta accettata:
Probabilmente è perché il tuo /etc/sudoers
file (o qualsiasi file che include) ha:
Defaults requiretty
...che rende sudo
richiedono un TTY. È noto che i sistemi Red Hat (RHEL, Fedora...) richiedono un TTY nei sudoers
predefiniti file. Ciò non fornisce alcun reale vantaggio in termini di sicurezza e può essere rimosso in sicurezza.
Red Hat ha riconosciuto il problema e verrà rimosso nelle versioni future.
Se la modifica della configurazione del server non è un'opzione, come soluzione per quella configurazione errata, potresti usare il -t
o -tt
opzioni per ssh
che genera uno pseudo-terminale sul lato remoto, ma attenzione che ha una serie di effetti collaterali.
-tt
è pensato per un uso interattivo. Mette il terminale locale in raw
modalità in modo da interagire con il terminale remoto. Ciò significa che se ssh
L'I/O non è da/verso un terminale, che avrà effetti collaterali. Ad esempio, tutto l'input verrà ripreso, caratteri speciali del terminale (^?
, ^C
, ^U
) comporterà un trattamento speciale; in uscita, LF
I messaggi verranno convertiti in CRLF
s... (vedi questa risposta a Perché questo file binario viene modificato? per maggiori dettagli.
Per ridurre al minimo l'impatto, puoi invocarlo come:
ssh -tt host 'stty raw -echo; sudo ...' < <(cat)
Il < <(cat)
eviterà l'impostazione del terminale locale (se presente) in raw
modalità. E stiamo usando stty raw -echo
per impostare la disciplina di linea del terminale remoto come pass-through (di fatto si comporta come la pipe che verrebbe utilizzata al posto di uno pseudo-terminale senza -tt
, sebbene ciò si applichi solo dopo l'esecuzione del comando, quindi è necessario ritardare l'invio di qualcosa per l'input fino a quando ciò non accade).
Nota che poiché l'output del comando remoto andrà a un terminale, ciò influenzerà comunque il suo buffering (che sarà basato sulla linea per molte applicazioni) e l'efficienza della larghezza di banda poiché TCP_NODELAY
è acceso. Anche con -tt
, ssh
imposta l'IPQoS su lowdelay
al contrario di throughput
. Potresti aggirare entrambi con:
ssh -o IPQoS=throughput -tt host 'stty raw -echo; sudo cmd | cat' < <(cat)
Inoltre, nota che significa che il comando remoto non può rilevare la fine del file sul suo stdin e lo stdout e lo stderr del comando remoto sono uniti in un unico flusso.
Correlati:Debian – Rimuovere utente e password all'accesso in Debian 9 Stretch?Quindi, dopotutto, non è una buona soluzione.
Se hai un modo per generare uno pseudo-terminale sull'host remoto (come con expect
, zsh
, socat
, perl
's IO::Pty
…), allora sarebbe meglio usarlo per creare lo pseudo-terminale per allegare sudo
a (ma non per I/O) e usa ssh
senza -t
.
Ad esempio, con 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'
Oppure con script
(qui assumendo l'implementazione da 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'
(supponendo (per entrambi) che la shell di accesso dell'utente remoto sia simile a Bourne).