我制作了一个脚本,它看起来像这样:
#!/usr/bin/expect -f
set ip [lindex $argv 0];
spawn ssh name@server
expect "assword"
set timeout 0.5
send "password\r"
expect "xxxxx"
set timeout 1
send "telnet $ip\r"
expect "assword"
send "password\r"
expect "xxxxxx"
send "xxxxxxx\r"
.
.
.
.
脚本继续到我的输出显示如下的位置:
Last update from 1.1.1.1 1d06h ago
Routing Descriptor Blocks:
* 1.1.1.1 from 2.2.2.2
我需要弄清楚如何提取这个始终唯一的 IP ( 1.1.1.1
) 并将其自动转发到我的脚本中,以便我可以继续。
答案1
有两个实例1.1.1.1
;假设第一个实例可以匹配,首先需要编写一个简单的脚本来生成所需的输出,并且还包括或多或少由远程设备完成的虚假提示:
#!/usr/bin/env expect
proc prompt {} { puts "prompt"; gets stdin; }
prompt
puts "Last update from 1.1.1.1 1d06h ago"
puts " Routing Descriptor Blocks:"
puts " * 1.1.1.1 from 2.2.2.2"
prompt
我称这个脚本为generator
;然后还需要另一个脚本来调用该脚本并与之交互。但首先转向如何快速迭代这些脚本的更改;在另一个终端我运行:
$ (echo consume; echo generate) | entr ./consume
...
consume
只要consume
或脚本发生更改,它就会运行该脚本generate
。然后我可以摆弄脚本以与提示进行交互,找到所需的输出,并对其应用正则表达式(阅读手册regexp(n)
):
#!/usr/bin/env expect
spawn -noecho ./generate
expect -ex prompt
send -- "before\r"
expect -ex prompt
# this is what I used to confirm that the required prompt block
# had been matched
#puts ">>>$expect_out(buffer)<<<"
regexp {Last update from ([^ ]+) } $expect_out(buffer) unused theip
puts ">>>$theip<<<"
send -- "after\r"
expect eof
此方法假设所需的输出由提示支撑;另一种选择是使用正则表达式的expect
行Last update ...
,但这可能更复杂。此外,此 IP 地址匹配实际上可以匹配任何内容;如果您需要验证文本是否确实是 IP 地址,请使用更精确的正则表达式。
其他问题:
- 你的超时时间非常短;如果所涉及的任何系统或网络速度缓慢,并且输出需要比给定的超时时间更长的时间才能到达,会发生什么情况?
- 没有太多的错误检查,如果系统
ssh
抛出主机密钥错误或提示,或者......