我对使用 expect 很陌生,对于将命令传递给 expect 脚本有点困惑,所以请耐心等待……我搜索了很多论坛,但似乎找不到使用 expect 脚本的示例用于获取用户输入的读取命令。
在我的 Korn shell 脚本中,我调用了一个 expect 脚本 (expectssh.exp) 以通过 ssh 登录到另一台主机并获取有关该主机网络配置的用户输入(网络接口(interface)卡号和子网掩码信息)。我将四个参数传递给 expect 脚本:远程主机 ip 地址、用户名、密码和要运行的命令列表。我的期望脚本如下:
#!/usr/bin/expect
# Usage: expectssh <host> <ssh user> <ssh password> <script>
set timeout 60
set prompt "(%|#|\\$) $"
set commands [lindex $argv 3];
spawn ssh [lindex $argv 1]@[lindex $argv 0]
expect {
"*assword:" {
send -- "[lindex $argv 2]\r"
expect -re "$prompt"
send -- "$commands\r"
}
"you sure you want to continue connecting" {
send -- "yes\r"
expect "*assword:"
send -- "[lindex $argv 2]\r"
expect -re "$prompt"
send -- "$commands\r"
}
timeout {
exit }
}
脚本运行良好,除了当它到达“读取”命令时,脚本不会继续或在用户按下 enter 后退出。它只是挂起。
我传递给expect脚本的命令及其调用如下:
SCRIPT='hostname > response.txt;netstat -rn;read net_card?"What is the network interface card number? " >> response.txt; read net_mask?"What is the subnet mask? " >> response.txt'
/usr/bin/expect ./expectssh.exp $hostip $usr $pswd "$SCRIPT"
关于如何在不挂起的情况下通过我的 expect 脚本传递读取命令有什么建议吗?
附带说明,因为我知道它会出现 - 我不允许进行基于 key 的自动 SSH 登录。我必须提示输入用户名和密码,这是通过调用此 expect 脚本的 Korn shell 脚本完成的。
感谢您提供的任何建议和帮助!
最佳答案
对于任何感兴趣的人,我可以通过做一些事情让 read
命令为用户输入工作:
(1) 将其放在 -re $prompt
block 中,而不是在密码输入后附加 send -- "$commands\r"
。
(2) 将命令硬编码到脚本中,而不是将它们传入。
(3) 在命令后加上 interact
语句,以便在用户响应之前不会输入下一个发送命令。
我的 expect block 现在看起来像这样:
expect {
-re "(.*)assword:" {
send -s "$pswd\r"
exp_continue
}
"denied, please try again" {
send_user "Invalid password or account.\n"
exit 5
}
"incorrect" {
send_user "Invalid password or account.\n"
exit 5
}
"you sure you want to continue connecting" {
send -s "yes\r"
exp_continue
}
-re $prompt {
set timeout -1
send -- "hostname > partnerinit\r"
expect -exact "hostname > partnerinit\r"
send -s "netstat -rn\r"
expect -re "$prompt"
send -- "read n_card?'Enter the network interface card number for this server (i.e. eth0): '\r"
interact "\r" return
send -- "\r"
send -- "echo \$n_card >> partnerinit\r"
send -- "msk=\$(cat /etc/sysconfig/network-scripts/ifcfg-\$n_card | grep NETMASK)\r"
send -- "msk=\$(echo \${msk#NETMASK=})\r"
send -- "echo \$msk >> partnerinit\r"
send -- "cat partnerinit\r"
set retval 0
}
timeout {
send_user "Connection to host $host timed out.\n"
exit 10
}
eof {
send_user "Connection to host $host failed.\n"
exit 1
}
}
我还更新了脚本以根据用户输入的网络接口(interface)卡号自动确定子网掩码。我注意到,在有多个接口(interface)卡的盒子中,很难自动找到网络接口(interface)卡号。最好从小处着手,让用户输入它,然后在整个脚本运行后对其进行微调/自动化。
现在我正在努力修改它以将我的 partnerinit 文件 scp 回我的本地主机并从每个预期条件返回有意义的退出状态。
关于linux - 如何从 expect 脚本中传递的 shell 'read' 命令返回?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30244608/