使用expect通过ssh进行2步登录

使用expect通过ssh进行2步登录,ssh,expect,Ssh,Expect,我试图创建一个通过ssh登录的脚本,但为了让它更难,我必须先通过ssh连接到一台服务器,然后再通过ssh连接到另一台服务器,才能连接到我想要连接的服务器。到目前为止,我的代码可以很好地让我进入第一台服务器,但是当它尝试用ssh连接到下一台服务器时,代码就不起作用了 #! /usr/bin/expect -f # set servers to ssh into set server1 "foo" set server2 "bar" # get username send_user -- "En

我试图创建一个通过ssh登录的脚本,但为了让它更难,我必须先通过ssh连接到一台服务器,然后再通过ssh连接到另一台服务器,才能连接到我想要连接的服务器。到目前为止,我的代码可以很好地让我进入第一台服务器,但是当它尝试用ssh连接到下一台服务器时,代码就不起作用了

#! /usr/bin/expect -f

# set servers to ssh into
set server1 "foo"
set server2 "bar"

# get username
send_user -- "Enter username: "
expect_user -re "(.*)\n"
set user $expect_out(1,string)

# get password
# don't ouput password to the user
stty -echo
send_user -- "Enter password for \"$user\": "
expect_user -re "(.*)\n"
send_user "\n"
stty echo
set password $expect_out(1,string)

# start the login
spawn ssh $user@$server1
expect "assword:"
send -- "$password\r"

# problems happen after here

# required to ssh from the <something> into <something else>
# the host name varies, e.g. host1, host2, host3, etc.
# so this just detects the last character
expect -re "\$ $"
send -- "ssh $user@$server2\r"
# sometimes it outputs this, sometimes it doesn't
expect "(yes/no)?"
send -- "yes\r"
expect "assword:"
send -- "$password\r"

interact
#/usr/bin/expect-f
#将服务器设置为ssh到
将服务器1设置为“foo”
设置服务器2“条”
#获取用户名
发送用户--“输入用户名:”
预期\u用户-re“(.*)\n”
设置用户$expect\u out(1,字符串)
#获取密码
#不要向用户输出密码
stty-echo
发送用户--“输入\“$user\”的密码:”
预期\u用户-re“(.*)\n”
发送\u用户“\n”
短回声
设置密码$expect\u out(1,字符串)
#开始登录
生成ssh$user@$server1
预期“assword:”
发送--“$password\r”
#问题就发生在这里
#需要从ssh连接到
#主机名各不相同,例如主机1、主机2、主机3等。
#所以这只是检测最后一个字符
expect-re“\$$”
发送--“ssh$user@$server2\r”
#有时它输出这个,有时它不输出
期望“(是/否)?”
发送--“是\r\n”
预期“assword:”
发送--“$password\r”
互动
两台服务器的用户名和密码相同

你犯了一个错误

expect -re "\$ $"; # WRONG
如果要将文字美元符号与行尾匹配,必须使用

expect -re "\\\$ $"; # CORRECT
它将匹配文字美元符号和行尾的空格

或者,为了匹配一些常见的已知提示,您可以定义一个变量,如

set prompt "#|>|%|\\\$ $"; # We escaped the `$` symbol with backslash to match literal '$' 
最后一个美元符号表示行尾

当使用
expect
时,我们必须附带
-re
标志以将其指定为正则表达式

expect -re $prompt
如果我们不知道某个特定单词是否会出现在输出中,或者我们不确定出现的顺序,则建议使用
exp\u continue

send -- "ssh $user@$server2\r"
# sometimes it outputs this, sometimes it doesn't
expect {
        "(yes/no)?" {send -- "yes\r";exp_continue}
        "ssword:" {send -- "$password\r"}
}
expect -re $prompt

回答得好。对于正则表达式,我通常使用不同的引号:
expect-re{\$}