每隔一段时间我会做一些类似的事情
ssh user@host sudo thing
我提醒说,ssh默认不会分配一个伪tty。 为什么不呢? 如果我使用ssh作为ssh -t会有什么好处?
主要的区别是交互的概念。 这与在脚本内部本地运行命令类似,而不是自己input。 不同之处在于,远程命令必须select默认,而非交互是最安全的。 (通常最诚实的)
Ctrl-c中断通常会导致ssh命令中的循环立即中断,但您的控制序列将被发送到远程服务器。 这导致需要“锤击”击键以确保当控制离开 ssh命令时,但在下一个ssh命令开始之前到达击键。 我会告诫不要在无人参与的脚本中使用ssh -t ,比如cron。 要求远程命令以交互方式进行input的非交互式shell要求各种各样的麻烦。
您也可以在自己的shell脚本中testingterminal的存在。 使用更新版本的bashtestingSTDIN:
# fd 0 is STDIN [ -t 0 ]; echo $?
ssh到ssh -t ,你可以期望在你的行结束时获得额外的回车。 它可能不是可见的,但它在那里; 它会显示为^M时,pipe道cat -e 。 然后,您必须花费额外的努力,确保这个控制代码不会被分配给您的variables,特别是如果您要将输出插入数据库。 这是与前面相同的bashtesting,但对于STDOUT:
# fd 1 is STDOUT [ -t 1 ]; echo $?
尽pipe可以解决这些问题,但是你不可避免地要忘记围绕它们devise脚本。 我们所有人都在做某件事。 你的团队成员也可能不会意识到/记住这个别名已经存在,当他们编写使用别名的脚本时,这又会给你带来麻烦。
将ssh -t为ssh -t就是一个很大的情况,在这种情况下你会违反最不让人意外的devise原则。 人们会遇到他们所不期望的问题,也不知道是什么原因造成的。
其他答案中没有提到的一个优点是,在没有伪terminal的情况下运行时, 不支持 〜C等SSH 转义字符 。 这使程序可以安全地传输可能包含这些序列的二进制文件。
使用伪terminal复制二进制文件:
$ ssh -t anthony@remote_host 'cat /usr/bin/free' > ~/free Connection to remote_host closed.
不使用伪terminal复制二进制文件:
$ ssh anthony@remote_host 'cat /usr/bin/free' > ~/free2
这两个文件是不一样的:
$ diff ~/free* Binary files /home/anthony/free and /home/anthony/free2 differ
用伪terminal拷贝的是损坏的:
$ 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进行数据传输的程序(如scp或rsync )尤为重要。 SCP协议如何工作的详细说明解释了SCP协议是如何由文本协议消息和二进制文件数据组成的混合体。
值得注意的是,即使使用了-t标志,如果OpenSSH ssh客户端检测到它的stdinstream不是terminal,它将拒绝分配一个伪terminal:
$ echo testing | ssh -t anthony@remote_host 'echo $TERM' Pseudo-terminal will not be allocated because stdin is not a terminal. dumb
你仍然可以强制OpenSSH客户端用-tt分配一个伪terminal:
$ echo testing | ssh -tt anthony@remote_host 'echo $TERM' xterm
在任何一种情况下,它(明智地)不关心stdout或stderr是否被redirect:
$ ssh -t anthony@remote_host 'echo $TERM' >| ssh_output Connection to remote_host closed.
在远程主机上,我们必须使用这个设置:
/etc/sudoers ... Defaults requiretty
没有sudo
$ 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.
解决scheme是禁用翻译换行符回车换行与stty -onlcr
$ ssh -t user@host stty -onlcr\; sudo echo -e 'foo\\nbar' | cat -e foo$ bar$ Connection to localhost closed.
从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, eg when implementing menu services. Multiple -t options force tty allocation, even if ssh has no local tty.
这可以让你得到一个“壳”到远程服务器。 对于不授予shell访问权限但允许使用SSH的服务器(例如,Github是SFTP访问的已知示例),使用此标志将导致服务器拒绝您的连接。
shell也有你所有的环境variables(如$PATH ),所以执行脚本通常需要一个tty才能工作。
考虑向后兼容性。
ssh的两个主要模式是交互式的,用tty和指定的命令(不带tty)进行交互式login,因为它们分别是rlogin和rsh的确切function。 ssh需要提供rlogin / rsh特性的超集才能成功取代。
所以默认是在ssh出生前决定的。 像“我想指定一个命令并得到一个tty”的组合必须被新的选项访问。 很高兴至less我们现在有这个select,不像我们使用rsh 。 我们没有交换任何有用的function来获得encryption连接。 我们有奖金function!