在学习非交互式登录 shell 的过程中,我遇到了两种通过 SSH 远程执行命令的方法。对我来说,它们看起来都是一样的。但不幸的是,事实并非如此。
使用命令echo "shopt login_shell; echo \$-" | ssh -l poweruser 192.168.1.67
,我得到以下输出。
Pseudo-terminal will not be allocated because stdin is not a terminal.
[email protected]'s password:
login_shell on
hBs
但通过命令ssh -l poweruser 192.168.1.67 "shopt login_shell; echo \$-"
,我得到了不同的输出。
[email protected]'s password:
login_shell off
hBc
您能否告诉我为什么在第二种情况下 shell 不是登录 shell,即使它提示输入密码。
答案1
如果一个命令指定后,它会在远程主机上执行,而不是在登录 shell 上执行。
原因是,在一种情况下您指定了一个命令,而在另一种情况下您没有指定,并且ssh
故意(根据设计)在这些情况下表现不同。
在您没有提供命令的情况下,会启动一个登录 shell,它会读取管道输入并执行它。在您确实提供命令的那个中,它被启动了。
提示输入密码是无关的。这是在启动 shell 或命令之前向服务器验证您的身份。
答案2
这是不精确的,但它可能是一种有用的看待方式:
echo … | ssh …
“看起来像”一个交互式会话——ssh
启动后从其标准输入读取 shell 命令。现在,当然,ssh
能区分它的 stdin 是管道还是 tty(或文件),但它可能不会费心这样做。以不同于 tty 的方式处理管道可能会使使用类似的东西变得更加困难expect
(手册页)。echo … | ssh …
感觉就像打电话给某人并要求他们做某事。有可能,您希望他们这样做立即地 (当您仍在打电话时),因此登录 shell 感觉更合适。使用,您可以指定在建立连接之前运行的命令。您不可能根据您看到的响应有条件地执行某些操作(除非出现问题时可能点击+ )。所以它不能是交互式的;这更像是
ssh … command
ssh
CtrlC批量处理。这感觉就像给某人发一封电子邮件并要求他们做某事。您不期望立即得到响应,因此登录 shell 感觉不太合适。
有关背景,请参阅为什么使用“登录”shell 而不是“非登录”shell? (其中——披露——唯一的答案是我写的)和 登录 Shell 和非登录 Shell 之间的区别?——尽管快速浏览了一下,我没有看到任何与这个问题直接相关的内容。