每隔一段时间我就会做一些类似的事情
ssh user@host sudo thing
Run Code Online (Sandbox Code Playgroud)
我还记得 ssh 默认不分配伪 tty。为什么不呢?如果我别名ssh为 ,我会失去什么好处ssh -t?
And*_*w B 83
主要区别在于交互性的概念。这类似于在脚本中本地运行命令,而不是自己键入命令。不同之处在于远程命令必须选择默认值,而非交互式是最安全的。(通常是最诚实的)
Ctrl-c中断通常会导致 ssh 命令的循环立即中断,但您的控制序列将被发送到远程服务器。这导致需要“敲击”击键以确保它在控制权离开ssh 命令时到达,但在下一个 ssh 命令开始之前。我会警告不要ssh -t在无人参与的脚本中使用,例如 cron。要求远程命令以交互方式输入的非交互式 shell 会带来各种麻烦。
您还可以测试您自己的 shell 脚本中是否存在终端。要使用较新版本的 bash 测试 STDIN:
# fd 0 is STDIN
[ -t 0 ]; echo $?
Run Code Online (Sandbox Code Playgroud)
ssh为 时ssh -t,您可以期望在行尾获得额外的回车符。你可能看不到它,但它就在那里;它将显示为通过^M管道传输到cat -e. 然后,您必须付出额外的努力来确保不会将此控制代码分配给您的变量,尤其是在您要将输出插入数据库时。这是与之前相同的 bash 测试,但针对 STDOUT:
# fd 1 is STDOUT
[ -t 1 ]; echo $?
Run Code Online (Sandbox Code Playgroud)
虽然可以解决这些问题,但您不可避免地会忘记围绕它们设计脚本。我们所有人都会在某个时候这样做。您的团队成员也可能没有意识到/记得这个别名已经到位,这反过来会在他们编写使用您的别名的脚本时给您带来问题。
Aliasing sshtossh -t是一种违反最小意外设计原则的情况;人们会遇到他们意想不到的问题,并且可能不明白是什么导致了这些问题。
Ant*_*gan 37
还没有在其他的答案被提及一个优点是,工作时没有一个伪终端,所述SSH转义字符如~C被不支持; 这使得程序可以安全地传输可能包含这些和其他控制字符的二进制文件。
如果没有伪终端,字符将“按原样”传输到远程主机:
$ printf "one\ntwo\n~Cthree\n" | ssh user@host tee 1
one
two
~Cthree
Run Code Online (Sandbox Code Playgroud)
如果您尝试强制分配伪终端,则包含~C会导致ssh>打印提示以允许用户输入 SSH 命令,从而中断传输。
$ printf "one\ntwo\n~Cthree\n" | ssh -tt user@host tee 2
ssh>
one
two
three
one
two
three
Run Code Online (Sandbox Code Playgroud)
甲~.序列更糟糕的是,因为它导致正在传输没有数据:
$ printf "one\ntwo\n~.three\n" | ssh -tt user@host tee 2
Connection to host closed.
Run Code Online (Sandbox Code Playgroud)
当分配伪终端时,软件流控制字符(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$
Run Code Online (Sandbox Code Playgroud)
使用伪终端,该Ctrl-S字符被解释为暂停输入流的信号,因此在遇到该字符后不再发送数据(除非Ctrl-Q在输入流中后面跟着一个字符)。
在这种情况下,强制分配伪终端会导致远程端的文件为空。
$ printf "one\ntwo\n^Sthree\n" | ssh -tt user@host tee 2
one
two
Run Code Online (Sandbox Code Playgroud)
在这种情况下,强制分配伪终端会导致远程端的文件包含所有三行但没有控制字符:
$ 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$
Run Code Online (Sandbox Code Playgroud)
使用伪终端,换行符(十进制 10,0AASCII 中的十六进制)也被转换为CRLF序列(0D0AASCII 中的十六进制)。
从前面的例子:
$ ssh -t user@host cat 1 | cat -vet
one^M$
two^M$
^Sthree^M$
Connection to host closed.
Run Code Online (Sandbox Code Playgroud)
$ ssh -t anthony@remote_host 'cat /usr/bin/free' > ~/free
Connection to remote_host closed.
Run Code Online (Sandbox Code Playgroud)
不使用伪终端复制二进制文件:
$ ssh anthony@remote_host 'cat /usr/bin/free' > ~/free2
Run Code Online (Sandbox Code Playgroud)
这两个文件不一样:
$ diff ~/free*
Binary files /home/anthony/free and /home/anthony/free2 differ
Run Code Online (Sandbox Code Playgroud)
用伪终端复制的那个被破坏了:
$ chmod +x ~/free*
$ ./free
Segmentation fault
Run Code Online (Sandbox Code Playgroud)
而另一个不是:
$ ./free2
total used free shared buffers cached
Mem: 2065496 1980876 84620 0 48264 1502444
-/+ buffers/cache: 430168 1635328
Swap: 4128760 112 4128648
Run Code Online (Sandbox Code Playgroud)
这对于诸如scp或rsync使用 SSH 进行数据传输的程序尤其重要。此的SCP协议如何工作的详细描述中解释了SCP协议如何由文本协议消息和二进制文件数据的混合物。
值得注意的是,即使使用了该-t标志,OpenSSHssh客户端如果检测到其stdin流不是终端,也会拒绝分配伪终端:
$ echo testing | ssh -t anthony@remote_host 'echo $TERM'
Pseudo-terminal will not be allocated because stdin is not a terminal.
dumb
Run Code Online (Sandbox Code Playgroud)
您仍然可以强制 OpenSSH 客户端使用以下命令分配伪终端-tt:
$ echo testing | ssh -tt anthony@remote_host 'echo $TERM'
xterm
Run Code Online (Sandbox Code Playgroud)
在任何一种情况下,它(明智地)都不关心是否stdout或被stderr重定向:
$ ssh -t anthony@remote_host 'echo $TERM' >| ssh_output
Connection to remote_host closed.
Run Code Online (Sandbox Code Playgroud)
小智 6
在远程主机上,我们必须进行以下设置:
/etc/sudoers
...
Defaults requiretty
Run Code Online (Sandbox Code Playgroud)
没有须藤
$ ssh -T user@host echo -e 'foo\\nbar' | cat -e
foo$
bar$
Run Code Online (Sandbox Code Playgroud)
并使用 sudo
$ ssh -T user@host sudo echo -e 'foo\\nbar' | cat -e
sudo: sorry, you must have a tty to run sudo
Run Code Online (Sandbox Code Playgroud)
使用 sudo 我们得到额外的回车符
$ ssh -t user@host sudo echo -e 'foo\\nbar' | cat -e
foo^M$
bar^M$
Connection to localhost closed.
Run Code Online (Sandbox Code Playgroud)
解决方案是禁用将换行符转换为回车换行符stty -onlcr
$ ssh -t user@host stty -onlcr\; sudo echo -e 'foo\\nbar' | cat -e
foo$
bar$
Connection to localhost closed.
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
76802 次 |
| 最近记录: |