Ho configurato sudoper funzionare senza una password, ma quando provo a ssh 'sudo Foo'ottenere ancora il messaggio di errore sudo: sorry, you must have a tty to run sudo.
Perché questo accade e come posso aggirarlo?
Ho configurato sudoper funzionare senza una password, ma quando provo a ssh 'sudo Foo'ottenere ancora il messaggio di errore sudo: sorry, you must have a tty to run sudo.
Perché questo accade e come posso aggirarlo?
Risposte:
Questo probabilmente perché il tuo /etc/sudoersfile (o qualsiasi altro file incluso) ha:
Defaults requiretty
... il che rende sudonecessario un TTY. È noto che i sistemi Red Hat (RHEL, Fedora ...) richiedono un TTY nel sudoersfile predefinito . Ciò non offre alcun reale vantaggio in termini di sicurezza e può essere rimosso in modo sicuro.
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 errata configurazione, è possibile utilizzare le opzioni -to -tta sshcui viene generato uno pseudo-terminale sul lato remoto, ma attenzione che ha un certo numero di lati effetti.
-ttè pensato per l'uso interattivo. Mette il terminale locale in rawmodalità in modo da interagire con il terminale remoto. Ciò significa che se l' sshI / O non proviene da / verso un terminale, ciò avrà effetti collaterali. Ad esempio, tutti gli input verrà eco indietro, caratteri speciali terminali ( ^?, ^C, ^U) causerà elaborazione speciale; sull'output, LFs verrà convertito in CRLFs ... (vedere questa risposta a Perché questo file binario viene modificato? per maggiori dettagli.
Per ridurre al minimo l'impatto, è possibile invocarlo come:
ssh -tt host 'stty raw -echo; sudo ...' < <(cat)
Il < <(cat)eviterà l'impostazione del terminale locale (se presente) in rawmodalità. E stiamo usando stty raw -echoper impostare la disciplina di linea del terminale remoto come pass through (in modo efficace, quindi si comporta come la pipe che verrebbe utilizzata al posto di uno pseudo-terminale senza -tt, anche se questo si applica solo dopo l'esecuzione di quel comando, quindi è necessario ritardare l'invio di qualcosa per l'input fino a quando ciò accade).
Si noti che poiché l'output del comando remoto verrà indirizzato a un terminale, ciò influenzerà comunque il suo buffering (che sarà basato su linea per molte applicazioni) e l'efficienza della larghezza di banda poiché TCP_NODELAYè attiva. Inoltre -tt, sshimposta IPQoS su lowdelayopposto a throughput. Puoi aggirare entrambi con:
ssh -o IPQoS=throughput -tt host 'stty raw -echo; sudo cmd | cat' < <(cat)
Inoltre, si noti che significa che il comando remoto non è in grado di rilevare la fine del file sul suo stdin e che lo stdout e lo stderr del comando remoto vengono uniti in un singolo flusso.
Quindi, dopotutto, non è un buon lavoro.
Se hai un ottenuto un modo per generare una pseudo-terminale sul host remoto (come con expect, zsh, socat, perls' IO::Pty...), allora sarebbe meglio usare che per creare la pseudo-terminale da allegare sudoa (ma non per I / O) e utilizzare sshsenza -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'
O 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).
Per impostazione predefinita, SUDO è configurato per richiedere un TTY. Cioè, SUDO dovrebbe essere eseguito da una shell di login. È possibile annullare questo requisito aggiungendo il -tpassaggio alla chiamata SSH:
ssh -t someserver sudo somecommand
L' -tassegnazione forze di una pseudo-tty.
Se si desidera eseguire questa operazione a livello globale, modificare /etc/sudoersper specificare !requiretty. Questo può essere fatto aa per utente, per gruppo o livello onnicomprensivo.
Usa la -tbandiera sshper forzare l'allocazione di tty.
$ ssh luci tty
not a tty
$ ssh luci -t tty
/dev/ttys003
$
-tper forzare l'allocazione quandoPseudo-terminal will not be allocated because stdin is not a terminal.
Ho riscontrato questo problema utilizzando Docker e Centos 7. Ho finito per fare quanto segue:
yum install -y sudo
sed -i -e 's/Defaults requiretty.*/ #Defaults requiretty/g' /etc/sudoers
Ho trovato questo trucco su https://hub.docker.com/r/liubin/fluentd-agent/~/dockerfile
Un'alternativa interessante è eseguire FreeIPA o IdM per gestire centralmente i tuoi utenti e le regole sudoer. È quindi possibile creare regole sudo e assegnare l'opzione
! requiretty
nella regola. Il comando verrà quindi eseguito come previsto. Avrai anche i vantaggi di gestire tutti i server e gli utenti da un unico set di configurazioni.
Ho avuto lo stesso problema. Nel mio caso, la soluzione era di due righe
myscript=$(cat ssh_test.sh)
ssh -t user@host "$myscript"
Spiegazione:
Inserire i comandi che si desidera eseguire (inclusi i comandi sudo) in uno script, ad esempio "ssh_test.sh".
Leggi l'intero script in una variabile chiamata "myscript".
Richiamare ssh con solo uno -t e fornire la variabile invece di un comando.
Prima di questo, mi sono imbattuto in problemi usando combinazioni di lettura da stdin e usando heredocs
Ho trovato questa domanda mentre cercavamo su Google e ho riscontrato questo errore per una ragione completamente diversa.
La mia correzione era quella di smettere di chiamare script shell downstream come sudodal mio script shell genitore, quando lo script shell genitore era già stato chiamato con sudo.
requirettynei suoi sudoer predefiniti. Sarà risolto nelle versioni più recenti