¿Por qué necesito un tty para ejecutar sudo si puedo sudo sin una contraseña?


226

He configurado sudopara ejecutar sin contraseña, pero cuando lo intento ssh 'sudo Foo', sigo recibiendo el mensaje de error sudo: sorry, you must have a tty to run sudo.

¿Por qué sucede esto y cómo puedo solucionarlo?

Respuestas:


290

Probablemente sea porque su /etc/sudoersarchivo (o cualquier archivo que incluya) tiene:

Defaults requiretty

... lo que hace que sudorequiera un TTY. Se sabe que los sistemas Red Hat (RHEL, Fedora ...) requieren un TTY en el sudoersarchivo predeterminado . Eso no proporciona ningún beneficio de seguridad real y se puede eliminar de forma segura.

Red Hat ha reconocido el problema y se eliminará en futuras versiones.

Si cambiar la configuración del servidor no es una opción, como una solución alternativa para esa configuración incorrecta, puede usar las opciones -to que generan un pseudo terminal en el lado remoto, pero tenga cuidado de que tenga un número de lados efectos-ttssh

-ttestá destinado para uso interactivo. Pone el terminal local en rawmodo para que pueda interactuar con el terminal remoto. Eso significa que si la sshE / S no es de / a un terminal, tendrá efectos secundarios. Por ejemplo, toda la entrada se hizo eco de vuelta, caracteres terminales especiales ( ^?, ^C, ^U) hará que el procesamiento especial; en la salida, LFs se convertirá en CRLFs ... (vea esta respuesta a ¿Por qué se cambia este archivo binario? para más detalles.

Para minimizar el impacto, puede invocarlo como:

ssh -tt host 'stty raw -echo; sudo ...' < <(cat)

Esto < <(cat)evitará la configuración del terminal local (si lo hay) en rawmodo. Y lo estamos utilizando stty raw -echopara establecer la disciplina de línea del terminal remoto a medida que pasa (efectivamente, para que se comporte como la tubería que se usaría en lugar de un pseudo-terminal sin -tt, aunque eso solo se aplica después de ejecutar ese comando, por lo que necesita retrasar el envío de algo para la entrada hasta que eso suceda).

Tenga en cuenta que dado que la salida del comando remoto irá a un terminal, eso afectará su almacenamiento en búfer (que estará basado en líneas para muchas aplicaciones) y la eficiencia del ancho de banda ya que TCP_NODELAYestá activado. También con -tt, sshestablece el IPQoS en lowdelaylugar de throughput. Podrías evitar ambos con:

ssh -o IPQoS=throughput -tt host 'stty raw -echo; sudo cmd | cat' < <(cat)

Además, tenga en cuenta que significa que el comando remoto no puede detectar el final del archivo en su stdin y que stdout y stderr del comando remoto se fusionan en una sola secuencia.

Entonces, no es un buen trabajo después de todo.

Si usted ha conseguido una manera de generar un pseudo-terminal en el host remoto (como con expect, zsh, socat, perl's IO::Pty...), entonces sería mejor utilizar eso para crear la pseudo-terminal para unir sudoa (pero no para E / S), y uso sshsin -t.

Por ejemplo, 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(aquí asumiendo la implementación desde 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'

(suponiendo (para ambos) que el shell de inicio de sesión del usuario remoto es similar a Bourne).


30

Por defecto, SUDO está configurado para requerir un TTY. Es decir, se espera que SUDO se ejecute desde un shell de inicio de sesión. Puede anular este requisito agregando el -tinterruptor a su invocación SSH:

ssh -t someserver sudo somecommand

La -tasignación de fuerzas de un pseudo-tty.

Si desea realizar esto globalmente, modifique /etc/sudoerspara especificar !requiretty. Esto se puede hacer aa por usuario, por grupo o nivel global.


55
No, eso no es lo predeterminado. Es solo la distribución redhat de sudo que tenía requirettyen sudoers por defecto. Se solucionará en versiones más recientes
Stéphane Chazelas

1
@StephaneChazelas +1 por aclararme que es en gran parte autóctono de Red Hat y sus hermanos y otro ++ si pudiera para el informe de error actual.
JRFerguson 01 de

18

Use la -tbandera sshpara forzar la asignación de tty.

$ ssh luci tty
not a tty
$ ssh luci -t tty
/dev/ttys003
$

Agregue un segundo -tpara forzar la asignación cuandoPseudo-terminal will not be allocated because stdin is not a terminal.
Samveen

11

Me encontré con este problema usando Docker y Centos 7. Terminé haciendo lo siguiente:

yum install -y sudo

sed -i -e 's/Defaults requiretty.*/ #Defaults requiretty/g' /etc/sudoers

Encontré este truco en https://hub.docker.com/r/liubin/fluentd-agent/~/dockerfile


1
Esta respuesta tenía más sentido para mí, usando Docker y CentOS 7 también. ¡Era fácil de entender y fácil de copiar / pegar!
DaShaun

1

Una alternativa interesante es ejecutar FreeIPA o IdM para administrar sus usuarios y reglas de sudoer de forma centralizada. Luego puede crear reglas de sudo y asignar la opción

! requiretty

en la regla El comando se ejecutará como se esperaba. También tendrá los beneficios de administrar todos los servidores y usuarios desde un único conjunto de configuraciones.


0

Tuve el mismo problema. En mi caso, la solución fue dos líneas.

myscript=$(cat ssh_test.sh)
ssh -t user@host "$myscript"

Explicación:

  • Coloque los comandos que desea ejecutar (incluidos los comandos sudo) en un script, por ejemplo, "ssh_test.sh".

  • Lea todo el script en una variable llamada "myscript".

  • Invoque ssh con solo uno -t y proporcione la variable en lugar de un comando.

Antes de esto, me encontré con problemas al usar combinaciones de lectura de stdin y usar heredocs


-1

Encontré esta pregunta mientras buscaba en Google y encontré este error por una razón completamente diferente.

Mi solución fue dejar de llamar scripts de shell descendentes a sudopartir de mi script de shell principal, cuando el script de shell principal ya se llamaba con sudo.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.