sudo
配置为在没有密码的情况下运行,但是当我尝试运行ssh 'sudo Foo'
时,仍然收到错误消息sudo: sorry, you must have a tty to run sudo
。为什么会发生这种情况,如何解决呢?
#1 楼
这可能是因为您的/etc/sudoers
文件(或其包含的任何文件)具有:Defaults requiretty
...这使得
sudo
需要TTY。已知Red Hat系统(RHEL,Fedora ...)在默认sudoers
文件中需要TTY。但这并没有提供真正的安全优势,可以安全地删除。Red Hat已经确认了该问题,并将在以后的发行版中将其删除。
如果更改服务器的配置这不是一个选择,作为针对该错误配置的解决方法,您可以对
-t
使用-tt
或ssh
选项,这会在远程端生成伪终端,但请注意,它具有许多副作用。 /> -tt
供交互式使用。它将本地终端置于raw
模式,以便您与远程终端进行交互。这意味着,如果ssh
I / O不是从终端到终端,则会有副作用。例如,所有输入将被回显,特殊的终端字符(^?
,^C
,^U
)将引起特殊处理;在输出时,LF
s将转换为CRLF
s ...(有关更多详细信息,请参见“为什么要更改此二进制文件?”的此答案。要最大限度地减少影响,可以将其调用为:
ssh -tt host 'stty raw -echo; sudo ...' < <(cat)
< <(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)
此外,请注意,这意味着远程命令无法检测其stdin以及文件的stdout和stderr上的文件结尾。远程命令合并到单个流中。
所以,毕竟不是很好的解决方法。
如果您有办法生成伪终端在远程主机上(例如
expect
,zsh
,socat
,perl
的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'
(假设(对于两者)远程用户的登录外壳都类似于Bourne)。
#2 楼
默认情况下,SUDO配置为要求TTY。也就是说,SUDO有望从登录外壳运行。您可以通过在SSH调用中添加-t
开关来满足此要求:ssh -t someserver sudo somecommand
-t
强制分配伪tty。如果要全局执行此操作,请修改
/etc/sudoers
以指定!requiretty
。可以按每个用户,每个组或所有级别进行。评论
不,这不是默认值。只是sudo的redhat发行版在其默认sudoers中具有requiretty。它将在新版本中修复
–StéphaneChazelas
2014年4月1日在20:28
@StephaneChazelas +1启发我说它很大程度上是Red Hat及其兄弟姐妹的本机,如果可以的话,请提供另一个++!
– JRFerguson
2014年4月1日在20:38
#3 楼
使用对-t
的ssh
标志来强制tty分配。$ ssh luci tty
not a tty
$ ssh luci -t tty
/dev/ttys003
$
评论
当由于stdin不是终端而不会分配伪终端时,添加第二个-t强制分配。
– Samveen
17年1月1日在9:35
#4 楼
我在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
评论
这个答案对我来说也是最有意义的,同时使用Docker和CentOS 7。这很容易理解,并且易于复制/粘贴!
–大Shaun
16年5月2日在18:58
#5 楼
一个有趣的替代方法是运行FreeIPA或IdM来集中管理用户和更严格的规则。然后,您可以创建sudo规则,并在规则中分配选项!requiretty
。然后该命令将按预期运行。您还可以从一组配置中管理所有服务器和用户。
#6 楼
我遇到过同样的问题。就我而言,解决方案是两行myscript=$(cat ssh_test.sh)
ssh -t user@host "$myscript"
说明:
放置要运行的命令(包括sudo命令)到脚本中,例如“ ssh_test.sh”。
将整个脚本读入一个名为“ myscript”的变量。
仅用-t调用ssh并提供该变量而不是命令。
在此之前,我遇到了使用从stdin读取和使用heredocs
的组合的问题
#7 楼
我在Googling时发现了这个问题,并且由于完全不同的原因遇到了此错误。我的解决方法是在已经调用了父Shell脚本的情况下,停止从父Shell脚本以
sudo
的形式调用下游Shell脚本。与sudo
。
评论
非常感谢您:我今天使用了最后一个技巧(脚本-qec ....)。我在前后添加了一些命令:ssh host'cmds before; SHELL = / bin / sh脚本-qec“在此处使用args <&3>&4 2>&5 3 <&-4>&-5>&-” sudo cmdsudoed“ / dev / null 3 <&0 4>&1 5>&2;此处的cmds'#之后的cmd不会显示...可能是由于所有这些&-?他们是强制性的吗? (如果我正确理解了顺序:它们检索stdin,stdout和stderr的当前值(= fd),将sudo的in / out / err重定向(复制)到相同的目的地,然后将其关闭以进行脚本处理?从而关闭外部也是stdin / out / err吗?)
–奥利维尔·杜拉克(Olivier Dulac)
20 Dec 3在13:23
此外,我记得在此站点上读过的文章不建议关闭fd0 1或2:[编辑:找到它:当然,它是从您那里来的:)):unix.stackexchange.com/a/446591/27616:我不知道在关闭3、4、5之后看不到命令的输出:这是否意味着它关闭了我的ssh shell的0、1和2?因此...我的后续命令可能最终在错误的地方书写? :/
–奥利维尔·杜拉克(Olivier Dulac)
20 Dec 3在13:35
@OlivierDulac,没有n>&-(或n <&-相同)关闭fd n。从现在开始,只有exec 0 <&-1 <&-2 <&-(或exec <&->&-2>&-)会关闭stdin / stdout / stderr。我们在脚本启动的shell中关闭sudo的fds 3、4、5,因为sudo和cmd都不需要它们,并且它们已经达到了目的(在脚本会话中还原原始的远程shell stdin / out / err)。我不知道为什么您在这里之后看不到cmds的输出。
–StéphaneChazelas
20 Dec 3'14:15
感谢您的回答,我也感到困惑,并且需要进一步测试以弄清为什么会这样...
–奥利维尔·杜拉克(Olivier Dulac)
20 Dec 7'在8:33