我编写了 active.ksh 脚本(基于 expect),以便自动登录到某些 Solaris 机器并执行 hostname 命令(登录到虚拟 IP 以验证哪个主机名是活动机器 - 我有两台集群 solaris 机器)
问题在于expect
;expect 发送密码字符串 (pass123) 并且它错过了密码问题,并且它仍然等待密码。
因此,实际上密码 (pass123) 是在密码问题之后输入的。在大多数情况下,expect 脚本工作正常,但有时它会错过密码。
问题示例
./active.ksh
spawn ssh 10.10.18.61
sh: /usr/local/bin/stty: not found
This computer system, including all related equipment, networks and network devices (specifically including Internet access),is provided only for authorized uss
Password: * my remark - pass123 string was missed the Password Question pass123
Password:
剧本
#!/bin/ksh
VIP_ADDRESS=10.10.18.61
expect_for_verify_which_active_machine=`cat << EOF
set timeout -1
spawn ssh $VIP_ADDRESS
expect {
")?" { send "yes\r" ; exp_continue }
Password: {send "pass123\r"}
}
expect > {send "hostname\r"}
expect > {send exit\r}
expect eof
EOF`
expect -c "$expect_for_verify_which_active_machine"
正确结果的示例
./active.ksh
[Friday, February 24, 2012 2:32:06 PM IST] INFO Verify which is active SMU machine
spawn ssh 10.10.18.61
sh: /usr/local/bin/stty: not found
This computer system, including all related equipment, networks and network devices (specifically including Internet access),is provided only for authorized uss
yes
Password:
Last login: Fri Feb 24 14:32:06 2012 from smu1a
This computer system, including all related equipment, networks and network devices (specifically including Internet access),is provided only for authorized uss
solaris1:/ ROOT > hostname
solaris1
solaris1:/ ROOT > exit
logout
Connection to 10.10.18.61 closed.
答案1
如果您在登录期间监视字符串,您将需要避免使用“密码:”,您会发现它并不总是大写的。
改变您的期望-re "(.*)assword:"
或"assword:"
往往会更有效地赶上潮流。
如果你发现时间还是太快,你可以在发送之前添加 sleep 1;
这是我期望使用的
expect {
"(yes/no)?" { send "yes\n" }
"passphrase" { send "\r" }
-re "(.*)assword:" { sleep 1; send -- "password\r" }
-re $prompt { return }
timeout { puts "un-able to login: timeout\n"; return }
eof { puts "Closed\n" ; return }
}
答案2
我完全不明白你为什么要使用expect
。由于你可以通过 ssh 访问远程主机,最简单的解决方案就是建立 ssh公钥认证明确为此目的;然后您可以简单地运行......
ssh 10.10.18.61 hostname
...一切都会正常工作*。即使使用,expect
您也做了太多工作,因为即使使用密码验证,您也可以发出上述命令,而不必担心使用 expect 与远程 shell 交互。您会发送类似以下内容:
#!/bin/sh
VIP_ADDRESS=10.10.18.61
expect <<EOF
spawn ssh $VIP_ADDRESS hostname
expect Password:
send "pass123\n"
expect eof
EOF
就是这样。
你可以使用该-d
标志调试你的期望脚本。在我的例子中,在调试模式下运行的上述期望脚本的输出包括以下内容:
expect: does "" (spawn_id exp4) match glob pattern "password:"? no
lars@localhost's password:
expect: does "lars@localhost's password: " (spawn_id exp4) match glob pattern "password:"? yes
expect: set expect_out(0,string) "password:"
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) "lars@localhost's password:"
send: sending "PASSWORD\n" to { exp4 }
myhost.example.com
expect: read eof
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) " \r\nobliquity.int.seas.harvard.edu\r\n"
这准确地显示了expect
匹配的内容和发送的内容。
* 从技术上讲,您可能必须解决一些主机密钥问题,但这很容易。