我正在尝试通过Expect脚本从交换机获取配置详细信息。
我通过shell手动调用时,下面的东西按预期工作正常。
但是,当通过php调用同一对象(以构建一个Web界面来调用它)时,Expect_out(buffer)并没有填满所有行,我的匹配失败了。
我正在尝试匹配设置的配置位与否。
同样,当手动调用代码时,代码也可以正常工作,只是通过php无法以某种方式填充Expect_out(buffer):(:(
工作代码。
#!/usr/bin/expect
set ip ROUTER_IP
set uname USER_NAME
set psd PASSWORD
set log_file -a "/tmp/script.log"
spawn /usr/bin/ssh $uname@$ip
expect {
"ord:" {
send "$psd\r"
expect {
"> " {
send "\r"
set cmd "show configuration | display set | match class | match rancid"
set values $expect_out(buffer)
send_log "\nbefore trim n match -$values-\n"
set values [string trim $values]
send_log "\nbefore match -$values-\n"
set found [regexp {match rancid\s+(.*)\s+\r\n\{.*} $values match px]
if { $found == 1 && $px != "" } {
puts "Rancid Exists... !!!"
send "exit\r"
exit 1
} else {
puts "Coundnt find Rancid ... !!!"
send "exit\r"
exit 2
}
}
"denied: " {
puts "ERROR: Access Denied"
exit 2
}
}
}
}
我是这样通过php调用的,
$res=shell_exec("/usr/bin/expect $scriptPath ");
我可以看到,设置为$ values的Expect_out(buffer)被log_file输出的一半命令所填充。
成功的Expect_out(缓冲区),
before trim match -show configuration | display set | match class | match rancid ^M
set system login user rancid class remote-backup^M
^M
{master:1}^M
USER_NAME@SWITCH> -
before match -show configuration | display set | match class | match rancid ^M
set system login user rancid class remote-backup^M
^M
{master:1}^M
USER_NAME@SWITCH>-
通过php调用时,Expect_out(buffer)看起来像这样,
before trim match -show configuration | display set | m^MUSER_NAME@SWITCH> -
before match -show configuration | display set | m^MUSER_NAME@SWITCH>-
以某种方式,当期望通过php调用的脚本时,缓冲区没有输出所有命令,并且匹配失败。
有人可以指导我怎么做。谢谢。
答案 0 :(得分:0)
为什么情况有所不同?好吧,有各种各样的可能原因。不同的时间可能是其中之一。这是非常的可能性,而且很难预防。您只需要编写代码以适应各种变化即可。幸运的是,这很容易。
通常不建议使用$expect_out(buffer)
本身,因为未定义了其中仅存储了多少数据。它可能具有匹配expect
ed模式所需的尽可能多的内容,但实际上并不能保证匹配得更多。我希望脚本更像这样:
#!/usr/bin/expect
set ip ROUTER_IP
set uname USER_NAME
set psd PASSWORD
set log_file -a "/tmp/script.log"
spawn /usr/bin/ssh $uname@$ip
# Less nesting here! Makes the code much simpler to read
expect "ord:"
send "$psd\r"
expect {
"> " {
send_log "logged in\n"
}
"denied: " {
puts "ERROR: Access Denied"
exit 2
}
}
# Classic code to read a multi-line result from a remote site, ONE LINE AT A TIME
set cmd "show configuration | display set | match class | match rancid"
send "$cmd\r"; # Had you forgotten this in pasting?
set values ""
expect {
-re {^(.*\S|)\r?\n} {
append values $expect_out(1,string) "\n"
exp_continue
}
"> " {
# Got the prompt again
}
}
# This is your code again
send_log "\nbefore trim n match -$values-\n"
set values [string trim $values]
send_log "\nbefore match -$values-\n"
set found [regexp {match rancid\s+(.*)\s+\r\n\{.*} $values match px]
if { $found == 1 && $px != "" } {
puts "Rancid Exists... !!!"
send "exit\r"
exit 1
} else {
puts "Coundnt find Rancid ... !!!"
send "exit\r"
exit 2
}
通常,您应该尝试对代码进行结构化,以便交错expect
和send
,尽管连续几个expect
序列也可以。但是,您可以将其视为好像send
直到下一个expect
才真正被处理。
请注意exp_continue
的使用。这是Expect的一项非常强大的功能,可让您保持当前的expect
语句进行更多匹配。它使您可以构建匹配器循环(例如我所做的循环),并大大简化了许多交互问题。出于善意,请尽量避免嵌套代码!程序足够困难,而且不会使其变得更加复杂!