我的命令行/bash fu 非常弱,但我正在努力磨练我的能力。希望有人可以提供帮助。
我编写了一个超级简单的expect
脚本,这样我就可以通过 SSH 连接到我们在工作中使用的无头盒子,同时还发送密码(由于我无法扩展的原因,我们无法使用公钥来自动记录日志)在)。剧本:
#!/usr/bin/expect -f
set timeout 30
spawn ssh -X ***@10.101.0.133 $argv
match_max 100000
expect "*?assword:*"
send -- "***\r"
interact
盒子里已经安装了开发者环境和Eclipse;大多数时候,我连接到它时,我最终会直接通过隧道进入 Eclipse 来处理我们保留在这个盒子上的一些代码,所以我通常最终使用script eclipse
.
我怎样才能将&
标志传递给expect,以便它将&符号视为我正在生成的ssh会话的参数?当我使用script eclipse &
它时,它只是在我的机器上运行后台脚本,而不是在远程机器上执行某些操作,但我希望能够将其发送&
到,script
以便当 Eclipse 在远程机器上启动时,我仍然可以使用该机器的 shell。
这可能是一个非常愚蠢的问题,但我们将不胜感激任何帮助。
更新:我想出了逃避&符号的方法(这对我来说绝对是一个“不废话”的时刻……嗯)。但这会带来一个新问题。似乎当我向脚本传递任何参数时,expect 命令永远不允许我进行交互;一旦传递的命令执行,SSH 会话就会终止。我猜这不是expect的限制,而是ssh行为的一部分。不过还是谢谢你的回答。
更新2:只是为了后代,我通过将脚本修改为如下所示来获得我想要的行为:
#!/usr/bin/expect -f
set timeout 30
spawn ssh -X ***@10.101.0.133
match_max 100000
expect "*?assword:*"
send -- "***\r"
send $argv
send -- "\r"
interact
答案1
如果您不必输入密码,您可以这样做
ssh -t 'eclipse & exec bash'
该-t
标志告诉 ssh 分配一个终端,即使您给它一个命令名称。远程 shell 必须是非交互式的,因为它正在执行命令,但它所做的最后一件事是exec bash
,即用新的 shell 实例替换自身,这是交互式的。 (替换bash
为zsh
或任何您最喜欢的外壳。)
如果您需要输入密码,则确实需要在某种终端中输入密码(expect
如果您要自动化该部分,这就是您需要的原因)。ssh
故意拒绝从命令行参数或文件读取密码。
可能有用的一件事是一劳永逸地创建一个主 SSH 连接,并搭载在它上面。只要主服务器正在运行,您就可以建立不需要任何身份验证的从服务器连接。将以下行放入您的~/.ssh/config
:
Host nickname
HostName 10.101.0.133
ControlPath=~/.ssh-control:%l:%p:%r
创建主连接ssh -MX nickname eclipse
(expect
如果您仍想自动传递密码,请在 内)。然后,只要 Eclipse 正在运行,就无需ssh nickname
重新进行身份验证。
答案2
Geekosaur 正确地指出你可以通过引用来传递 & 符号,(你也可以用 like 来逃避它script eclipse \&
)但是我们也许可以在这里建议更好的方法。看来您已经编写了一个 Expect 脚本,用于使用您的密码 ssh 到另一台计算机并执行命令。
您应该知道,从实用的角度和安全的角度来看,这都不是一个很好的解决方案。实际上,整个情况很脆弱,几种潜在的情况可能会导致它崩溃,并且调试过程会很混乱。从安全角度来说是疯狂的因为你在另一台机器上的系统密码保存在某个地方的文本文件中!
有一个更好的办法!基于密钥的身份验证就是为了解决这个问题而建立的。您创建密钥对(一部分在服务器上,另一部分在客户端上),无需密码即可进行身份验证。这允许您从脚本运行 ssh,而无需使用 Expect 并且无需在任何地方保存密码。作为额外的步骤,您甚至可以使用密码短语加密本地密钥,并使用代理或密钥环管理器将密钥加载到 shell 中,然后再运行任何需要使用它的脚本。
编辑:我错过了你说你不能使用公钥身份验证。这是疯狂的言论。我留下我的答案是为了那些可能也错过了要求并且没有意识到你的脚本是黑客的读者的利益:)
答案3
使用引用: script 'eclipse &'
. (请注意,您这样做不是$argv
脚本中的引用expect
; Tcl 遵循与 不同的规则sh
。)