首先我需要说我知道使用公钥和私钥,但这并没有解决我的问题。我也知道,我可以使用两个脚本(一个与password1和第二个与password2),并运行它们两次,但我想知道为什么以下没有工作。我试图使期望的脚本,将通过ssh连接,并检查如果两个密码中的一个是正确的。为此,我正在检查脚本的退出代码:
- 0 - password1正确
- 1 - password2正确
- 2,3,4,5,6 -其他一些退出代码,由这篇文章所隐含:期望发送怪异建筑
在远程机器上可以有更多可能的登录提示,我想使这个脚本尽可能通用,所以我不能依赖登录提示字符串。到目前为止,我有以下代码:
#!/usr/local/bin/expect
set username "username";
set remote_server "machine";
set password1 "badpassword";
set password2 "goodpassword";
set timeout 5;
set pretype 0;
set retcode 0;
if { $pretype == 0 } {
spawn ssh -q ${username}@${remote_server}
expect {
"no)?" { send "yesr"; }
"denied" {
puts "Can't login to $remote_server. Check username and passwordn";
set retcode 2;
}
"telnet:" {
puts "Can't connect to $remote_server via SSH or Telnet. Something went definitely wrongn";
set retcode 3;
}
"failed" {
puts "Host $remote_server exists. Check ssh_hosts filen";
set retcode 4;
}
timeout {
puts "Timeout problem. Host $remote_server doesn't respondn";
set retcode 5;
}
"refused" {
puts "Host $remote_server refused to SSH. That is insecure.n";
set retcode 6;
}
"assword:" { set pretype 1; send "${password1}r"; }
}
} else {
expect{
"assword:" { send "${password2}r"; exit 1; }
timeout { exit 0; }
}
}
背后的想法是:如果我输入错误的密码,我将有第二次机会输入正确的密码。所以如果我第一次输入错误的密码,我的脚本应该继续在else分支(因为我set pretype to 1
)。这里我期待再次输入密码的提示。所以我将发送第二个密码并退出代码1 (password2是OK的)。如果else分支中的超时过期("password:"字符串不匹配),很可能我已经有登录提示,所以脚本将以代码0退出(password1是OK的)。但是这不起作用,如果我运行这个内部调试器,我看到的最后一行是:
send: sending "badpasswordrr" to { exp4 }
我不知道为什么会发生这种情况,但似乎脚本从未到达else分支。非常感谢
if
块中的set pretype 1
无法使其再次进入else
块。没有任何编程语言能做到这一点。这里需要一个类似于的循环(使用while
或exp_continue
)。
示例如下:
#!/usr/bin/expect
set passwords { bad1 bad2 bad3 good }
spawn ssh -o PreferredAuthentications=keyboard-interactive
-o NumberOfPasswordPrompts=[llength $passwords] root@tree
set try 0
expect {
"Password: " {
if { $try >= [llength $passwords] } {
send_error ">>> wrong passwordsn"
exit 1
}
send [lindex $passwords $try]r
incr try
exp_continue
}
"bash-4.2" {
interact
}
timeout {
send_error ">>> timed outn"
exit 1
}
}