使用 ssh 传输时终端分配会破坏文件

使用 ssh 传输时终端分配会破坏文件

我曾经ssh使用以下方法解压远程文件:

ssh host "cat file.tgz" | tar xf -

这工作得很好。但是我注意到在使用强制命令时,pty 分配会更改命令的输出:

ssh host -T "cat file.tgz" >first_file
ssh host -t "cat file.tgz" >second_file

这里第一个文件很好,但第二个文件已损坏。

为什么 pty 的分配会改变输出?

答案1

它有助于阅读ssh手册页:

 -T      Disable pseudo-tty allocation.                                     

 -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.

当你告诉它分配A伪tty,远程端的任何进程都可以看到该连接是一个“真实”终端,并且由于该连接是交互式的,因此将发送附加消息。在 shell 初始化中,它还可以设置终端模式,您可以使用 进行检查stty -a。终端模式用于翻译在键盘输入和主机之间,以及从主机发送到终端的文本之间:

  • 没有初始化时,连接不是终端,并且不进行任何转换。
  • 初始化时,终端会将换行符 ( \n) 转换为回车换行符 (0x0d、0x0a)。它还将(对于大多数用户)将制表符转换为空格。

所描述的效果是针对翻译。没有那个,你的交互的会话将“阶梯”穿过屏幕并且无法使用。

您的 shell 还可能打印附加信息,但对于单个命令,建议@kba 具有误导性,因为 shell 通常不会发送提示,以及上述的 ssh 控制~C适用于输入而不是输出

当运行到终端时,ssh 也会在关闭连接时打印一条消息。但这被写入标准错误。

答案2

为什么 pty 的分配会改变输出?

因为远程端(具有分配的终端)将为您的本地终端“注入”控制字符(基本上是C0和C1控制代码)。由于您的本地端不是终端,而是文件,因此它只是将它们转储到该文件中。

SSH 正在尽力猜测您想要什么(如果 stdin 不是 TTY,那么它不会分配远程 TTY,除非您添加-tt开关)。该选项的存在是有原因的,如果您想要二进制传输,您不希望终端弄乱您的文件。

您只需传输小文件然后十六进制转储即可看到此行为:

$ ssh -t host "cat test" > /tmp/test.t
$ ssh host "cat test" > /tmp/test
$ hexdump -C /tmp/test
00000000  0a 2a 20 46 72 69 20 46  65 62 20 31 32 20 32 30  |.* Fri Feb 12 20|
00000030  6d 3e 20 33 2e 34 2e 31  2d 31 0a 2d 20 4e 65 77  |m> 3.4.1-1.- New|

$ hexdump -C /tmp/test.t
00000000  0d 0a 2a 20 46 72 69 20  46 65 62 20 31 32 20 32  |..* Fri Feb 12 2|
00000030  6f 6d 3e 20 33 2e 34 2e  31 2d 31 0d 0a 2d 20 4e  |om> 3.4.1-1..- N|

对我来说,区别仅在于0d 0a每个新行之前的两个字节,但可能还有更多(linux 行 Newline 仅是\n,但终端同时获取两者\r\n)。

相关内容