AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 593399
Accepted
Chas. Owens
Chas. Owens
Asked: 2014-05-07 06:06:07 +0800 CST2014-05-07 06:06:07 +0800 CST 2014-05-07 06:06:07 +0800 CST

在 ssh 中不分配终端有什么好处?

  • 772

每隔一段时间我会做类似的事情

ssh user@host sudo thing

并且提醒我 ssh 默认情况下不分配伪 tty。为什么不呢?ssh如果我别名为 ,我会失去什么好处ssh -t?

ssh
  • 5 5 个回答
  • 84882 Views

5 个回答

  • Voted
  1. Best Answer
    Andrew B
    2014-05-07T07:02:43+08:002014-05-07T07:02:43+08:00

    主要区别在于交互性的概念。这类似于在脚本中本地运行命令,而不是自己输入命令。不同之处在于远程命令必须选择默认值,非交互是最安全的。(通常是最诚实的)

    标准输入

    • 如果分配了 PTY,应用程序可以检测到这一点,并知道在不破坏任何东西的情况下提示用户进行额外输入是安全的。如果没有终端,有很多程序会跳过提示用户输入的步骤,这是一件好事。否则会导致脚本不必要地挂起。
    • 在命令执行期间,您的输入将被发送到远程服务器。这包括控制序列。虽然Ctrl-c中断通常会导致 ssh 命令上的循环立即中断,但您的控制序列将改为发送到远程服务器。这导致需要“敲击”击键以确保它在控制离开ssh 命令时但在下一个 ssh 命令开始之前到达。

    我会警告不要ssh -t在无人看管的脚本中使用,例如 crons。要求远程命令以交互方式进行输入的非交互式 shell 会带来各种麻烦。

    您还可以在自己的 shell 脚本中测试终端是否存在。使用较新版本的 bash 测试 STDIN:

    # fd 0 is STDIN
    [ -t 0 ]; echo $?
    

    标准输出

    • 当别名ssh为 时ssh -t,你可以期望在你的行尾得到一个额外的回车。您可能看不到它,但它就在那里;它会显示为^M当管道传输到cat -e. 然后,您必须付出额外的努力来确保不会将该控制代码分配给您的变量,特别是如果您要将该输出插入到数据库中。
    • 还有一种风险是程序会假设它们可以呈现对文件重定向不友好的输出。通常,如果您要将 STDOUT 重定向到文件,程序会识别您的 STDOUT 不是终端并忽略任何颜色代码。如果 STDOUT 重定向来自ssh 客户端的输出,并且有一个与客户端远程端关联的 PTY,则远程程序无法进行这种区分,并且您最终会在输出文件中出现终端垃圾。将输出重定向到连接远程端的文件仍应按预期工作。

    这是与之前相同的 bash 测试,但针对 STDOUT:

    # fd 1 is STDOUT
    [ -t 1 ]; echo $?
    

    虽然可以解决这些问题,但您不可避免地会忘记围绕它们设计脚本。我们所有人都在某个时候做。您的团队成员也可能没有意识到/记得这个别名已经存在,这反过来会在他们编写使用您的别名的脚本时给您带来问题。

    别名ssh为ssh -t在很大程度上违反了最小意外的设计原则;人们会遇到他们没有预料到的问题,并且可能不明白是什么原因造成的。

    • 86
  2. Anthony Geoghegan
    2016-01-05T08:10:16+08:002016-01-05T08:10:16+08:00

    SSH 转义/控制字符和二进制文件的传输

    其他答案中没有提到的一个优点是,在没有伪终端的情况下运行时,不支持SSH转义字符等;这使得程序可以安全地传输可能包含这些和其他控制字符的二进制文件。~C

    如果没有伪终端,字符将“按原样”传输到远程主机:

    $ printf "one\ntwo\n~Cthree\n" | ssh user@host tee 1
    one
    two
    ~Cthree
    

    如果您尝试强制分配一个伪终端,包含~C会导致ssh>打印提示以允许用户输入 SSH 命令,从而中断传输。

    $ printf "one\ntwo\n~Cthree\n" | ssh -tt user@host tee 2
    
    ssh>
    one
    two
    three
    one
    two
    three
    

    序列更~.糟糕,因为它导致没有数据被传输:

    $ printf "one\ntwo\n~.three\n" | ssh -tt user@host tee 2
    Connection to host closed.
    

    软件流控

    分配伪终端时,也可以对软件流控制字符(XON/XOFF)进行特殊处理。

    $ printf "one\ntwo\n^Sthree\n" | ssh user@host tee 1
    one
    two
    three
    
    $ ssh user@host cat -vet 1
    one$
    two$
    ^Sthree$
    

    使用伪终端,该Ctrl-S字符被解释为暂停输入流的信号,因此在遇到该字符后不能再发送数据(除非它后面Ctrl-Q是输入流中的字符)。

    在这种情况下,强制分配伪终端会导致远程端的文件为空。

    $ printf "one\ntwo\n^Sthree\n" | ssh -tt user@host tee 2
    one
    two
    

    在这种情况下,强制分配伪终端会导致远程端的文件包含所有三行但没有控制字符:

    $ printf "one\ntwo\n^Sthree^Q\n" | ssh -tt user@host tee 2
    one
    two
    three
    one
    two
    three
    
    $ ssh user@host cat -vet 2
    one$
    two$
    three$
    

    行尾字符的转换

    使用伪终端,换行字符(十进制 10,0AASCII 中的十六进制)也被转换为CRLF序列(0D0AASCII 中的十六进制)。

    从前面的例子:

    $ ssh -t user@host cat 1 | cat -vet
    one^M$
    two^M$
    ^Sthree^M$
    Connection to host closed.
    

    使用伪终端复制二进制文件

    $ ssh -t anthony@remote_host 'cat /usr/bin/free' > ~/free
    Connection to remote_host closed.
    

    在不使用伪终端的情况下复制二进制文件:

    $ ssh anthony@remote_host 'cat /usr/bin/free' > ~/free2
    

    这两个文件不一样:

    $ diff ~/free*
    Binary files /home/anthony/free and /home/anthony/free2 differ
    

    使用伪终端复制的那个已损坏:

    $ chmod +x ~/free*
    $ ./free
    Segmentation fault
    

    而另一个不是:

    $ ./free2
                 total       used       free     shared    buffers     cached
    Mem:       2065496    1980876      84620          0      48264    1502444
    -/+ buffers/cache:     430168    1635328
    Swap:      4128760        112    4128648
    

    通过 SSH 传输文件

    这对于诸如使用 SSH 进行数据传输的程序尤其scp重要rsync。对 SCP 协议如何工作的详细描述解释了 SCP 协议如何由文本协议消息和二进制文件数据的混合组成。


    OpenSSH 帮助保护您免受自己的伤害

    值得注意的是,即使使用了该-t标志,如果 OpenSSH客户端检测到其流不是终端ssh,它也会拒绝分配伪终端:stdin

    $ echo testing | ssh -t anthony@remote_host 'echo $TERM'
    Pseudo-terminal will not be allocated because stdin is not a terminal.
    dumb
    

    您仍然可以强制 OpenSSH 客户端分配一个伪终端-tt:

    $ echo testing | ssh -tt anthony@remote_host 'echo $TERM'
    xterm
    

    在任何一种情况下,它(明智地)都不关心是否stdout或被stderr重定向:

    $ ssh -t anthony@remote_host 'echo $TERM' >| ssh_output
    Connection to remote_host closed.
    
    • 39
  3. Christophe Morio
    2016-08-02T04:51:20+08:002016-08-02T04:51:20+08:00

    在远程主机上,我们必须使用此设置:

    /etc/sudoers
    ...
    Defaults requiretty
    

    没有须藤

    $ ssh -T user@host echo -e 'foo\\nbar' | cat -e
    foo$
    bar$
    

    和 sudo

    $ ssh -T user@host sudo echo -e 'foo\\nbar' | cat -e
    sudo: sorry, you must have a tty to run sudo
    

    使用 sudo 我们得到额外的回车

    $ ssh -t user@host sudo echo -e 'foo\\nbar' | cat -e
    foo^M$
          bar^M$
                Connection to localhost closed.
    

    解决方案是禁用转换换行符到回车换行符stty -onlcr

    $ ssh -t user@host stty -onlcr\; sudo echo -e 'foo\\nbar' | cat -e
    foo$
        bar$
            Connection to localhost closed.
    
    • 4
  4. user193597
    2014-05-07T09:24:48+08:002014-05-07T09:24:48+08:00

    考虑向后兼容性。

    ssh 的两种主要模式是带 pty 的交互式登录和不带 pty 的指定命令,因为它们分别是rlogin和的确切功能rsh。ssh 需要提供rlogin/rsh功能的超集才能成功作为替代品。

    所以默认值是在 ssh 诞生之前决定的。必须使用新选项访问诸如“我想指定一个命令并获得一个 pty”之类的组合。很高兴至少我们现在有了这个选项,不像我们以前使用rsh. 我们没有放弃任何有用的功能来获得加密连接。我们有奖励功能!

    • 1
  5. Nathan C
    2014-05-07T06:45:37+08:002014-05-07T06:45:37+08:00

    来自man ssh:

     -t      Force pseudo-tty allocation.  This can be used to execute arbi-
             trary screen-based programs on a remote machine, which can be
             very useful, e.g. when implementing menu services.  Multiple -t
             options force tty allocation, even if ssh has no local tty.
    

    这允许您获得远程服务器的各种“外壳”。对于不授予 shell 访问权限但允许 SSH 的服务器(即,Github 是 SFTP 访问的一个已知示例),使用此标志将导致服务器拒绝您的连接。

    shell 还包含所有环境变量(如$PATH),因此执行脚本通常需要一个 tty 才能工作。

    • 0

相关问题

  • 如何最好地设置 ssh 隧道以访问远程网络 (Linux)

  • SSH 和重定向

  • 通过 SSH 会话使用 NET USER 命令拒绝访问

  • SSH 服务器零日漏洞利用 - 保护自己的建议

  • ubuntu apt-get upgrade - 如何在 shell 中单击确定?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve