如果我可以在没有密码的情况下进行sudo,为什么需要tty来运行sudo?


226

我已经配置sudo为在没有密码的情况下运行,但是当我尝试运行时ssh 'sudo Foo',仍然收到错误消息sudo: sorry, you must have a tty to run sudo

为什么会发生这种情况,我该如何解决?

Answers:


290

那可能是因为您的/etc/sudoers文件(或其包含的任何文件)具有:

Defaults requiretty

...这sudo需要TTY。已知Red Hat系统(RHEL,Fedora ...)在默认sudoers文件中需要TTY 。这并没有提供真正的安全优势,可以安全删除。

红帽已确认该问题,它将在以后的版本中删除。

如果不能更改服务器的配置,则可以使用-t-tt选项ssh在远程端生成伪终端,以解决该错误配置的变通方法,但是请注意,它具有许多方面效果。

-tt用于交互使用。它将本地终端置于raw模式,以便您与远程终端进行交互。这意味着,如果sshI / O不是从终端到终端,则会有副作用。例如,所有的输入将被回送,特殊终端字符(^?^C^U)将导致特殊的处理; 在输出时,LFs将转换为CRLFs ...(有关更多详细信息,请参见“ 为什么要更改此二进制文件?”的此答案

为了最大程度地减少影响,可以按以下方式调用它:

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

< <(cat)将避免在本地终端的(如果有的话)的设定raw模式。而且我们正在使用stty raw -echo将远程终端的线路规则设置为直通(有效地使其行为类似于将使用的管道代替不带的伪终端-tt,尽管仅在运行该命令后才适用),因此您需要以延迟发送某些东西作为输入,直到发生这种情况为止)。

请注意,由于远程命令的输出将到达终端,因此自打开以来,这仍将影响其缓冲(对于许多应用程序将基于行)和带宽效率TCP_NODELAY。另外-ttssh将IPQoS设置lowdelaythroughput。您可以使用以下两种方法来解决:

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

另外,请注意,这意味着远程命令无法在其stdin上检测到文件结尾,并且远程命令的stdout和stderr合并为单个流。

因此,毕竟不是很好的解决方法。

如果你一个有一个的方式来产卵远程主机上的伪终端(像expectzshsocatperlIO::Pty...),那么这将是更好地使用它来创建伪终端连接sudo(但不适用于I / O),并且ssh不带-t

例如,使用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'

或与script(此处假设从实现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'

(假设(对于这两者而言)远程用户的登录Shell类似于Bourne)。


30

默认情况下,SUDO配置为要求TTY。也就是说,SUDO有望从登录外壳运行。您可以通过将-t开关添加到SSH调用中来满足此要求:

ssh -t someserver sudo somecommand

-t伪tty 的力量分配。

如果要全局执行此操作,请修改/etc/sudoers以指定!requiretty。可以按每个用户,每个组或所有级别进行。


5
不,这不是默认值。requiretty默认sudoer中只有sudo的redhat发行版。这将是固定在新版本
斯特凡Chazelas

1
@StephaneChazelas +1启发我说它很大程度上是Red Hat及其兄弟姐妹的本机,而如果我可以查看当前的错误报告,则为++!
JRFerguson 2014年



1

一个有趣的替代方法是运行FreeIPA或IdM来集中管理用户和更严格的规则。然后,您可以创建sudo规则并分配选项

!requiretty

在规则中。然后该命令将按预期运行。您还可以从一组配置中管理所有服务器和用户。


0

我遇到过同样的问题。就我而言,解决方案是两行

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

说明:

  • 将要运行的命令(包括sudo命令)放入脚本中,例如“ ssh_test.sh”。

  • 将整个脚本读取到一个名为“ myscript”的变量中。

  • 仅用-t调用ssh并提供变量而不是命令。

在此之前,我遇到了使用从stdin读取和使用heredocs的组合的问题


-1

我在Googling时发现了这个问题,并且由于完全不同的原因遇到了此错误。

我的解决方法是sudo,当已经使用调用了父外壳脚本时,停止从我的父外壳脚本中调用下游外壳脚本sudo

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.