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

mer*_*011 232 ssh sudo tty

我已配置sudo为无需密码即可运行,但是当我尝试时ssh 'sudo Foo',仍然收到错误消息sudo: sorry, you must have a tty to run sudo

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

Sté*_*las 303

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

Defaults requiretty
Run Code Online (Sandbox Code Playgroud)

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

Red Hat 已经承认了这个问题,它将在未来的版本中删除。

如果更改服务器的配置不是一个选项,作为该错误配置的解决方法,您可以使用-tor-tt选项ssh在远程端生成一个伪终端,但要注意它有多个端效果。

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

为了尽量减少影响,您可以将其调用为:

ssh -tt host 'stty raw -echo; sudo ...' < <(cat)
Run Code Online (Sandbox Code Playgroud)

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

请注意,由于远程命令的输出将发送到终端,因此仍会影响其缓冲(对于许多应用程序将基于行)和带宽效率,因为它TCP_NODELAY已打开。还使用-tt,ssh将 IPQoS 设置lowdelay为与throughput. 您可以通过以下方式解决两者:

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

另请注意,这意味着远程命令无法检测其标准输入上的文件结尾,并且远程命令的标准输出和标准错误将合并为一个流。

所以,毕竟不是很好的解决方法。

如果您有办法在远程主机上生成伪终端(例如使用expect, zsh, socat, perl's IO::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'
Run Code Online (Sandbox Code Playgroud)

或者使用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'
Run Code Online (Sandbox Code Playgroud)

(假设(对于两者)远程用户的登录 shell 是类似 Bourne 的)。


JRF*_*son 31

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

ssh -t someserver sudo somecommand
Run Code Online (Sandbox Code Playgroud)

-t一个伪 tty的部队分配。

如果要全局执行此操作,请修改/etc/sudoers以指定!requiretty. 这可以按每个用户、每个组或包罗万象的级别来完成。

  • 不,这不是默认设置。只有 sudo 的 redhat 发行版在其默认的 sudoer 中有 `requiretty`。[它将在新版本中修复](https://bugzilla.redhat.com/show_bug.cgi?id=1020147) (5认同)

Kyl*_*nes 18

使用-t标志来ssh强制 tty 分配。

$ ssh luci tty
not a tty
$ ssh luci -t tty
/dev/ttys003
$
Run Code Online (Sandbox Code Playgroud)


小智 11

我在使用 Docker 和 Centos 7 时遇到了这个问题。我最终做了以下事情:

yum install -y sudo

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

我在https://hub.docker.com/r/liubin/fluentd-agent/~/dockerfile发现了这个黑客