expect_out(buffer)在通过php调用时不会捕获所有数据

expect_out(buffer)在通过php调用时不会捕获所有数据,php,tcl,expect,Php,Tcl,Expect,我试图通过expect脚本从交换机获取配置详细信息当我通过shell手动调用时,以下工件工作正常。 但是,当同样的调用via时,php(构建一个web界面来调用它)不知何故地expect_out(缓冲区)没有填满所有的行,我的匹配失败。 我正在尝试匹配或不匹配配置位集。 同样,当手动调用代码时,代码也可以工作,只是通过php,它无法以某种方式填充expect_out(缓冲区):(:( 工作代码。 #!/usr/bin/expect set ip ROUTER_IP set uname USER_

我试图通过expect脚本从交换机获取配置详细信息
当我通过shell手动调用时,以下工件工作正常。
但是,当同样的调用via时,php(构建一个web界面来调用它)不知何故地expect_out(缓冲区)没有填满所有的行,我的匹配失败。

我正在尝试匹配或不匹配配置位集。
同样,当手动调用代码时,代码也可以工作,只是通过php,它无法以某种方式填充expect_out(缓冲区):(:(

工作代码。

#!/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 ");
before trim match -show configuration | display set | m^MUSER_NAME@SWITCH> -

before match -show configuration | display set | m^MUSER_NAME@SWITCH>-
我可以看到,expection out(buffer)被设置为$values,它被日志文件输出的一半命令填充。

成功期望输出(缓冲区)

当通过php调用时,expect_out(缓冲区)如下所示,

$res=shell_exec("/usr/bin/expect $scriptPath ");
before trim match -show configuration | display set | m^MUSER_NAME@SWITCH> -

before match -show configuration | display set | m^MUSER_NAME@SWITCH>-

不知何故,当通过php调用expect脚本时,buffer没有输出所有命令,匹配失败。
有人能告诉我可能的错误是什么。谢谢。

为什么事情会不同?可能有各种各样的原因。不同的时间可能是其中之一;这很有可能,也很难防止。你只需要编写代码以适应变化;幸运的是,这相当容易

一般来说,不建议使用
$expect\u 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
s和
send
s交织在一起,虽然一行中有几个
expect
s可以。但是,您可以将其视为直到下一个
expect
才真正处理
send


请注意使用了
exp\u continue
。这是Expect的一个非常强大的功能,它可以让当前的
Expect
语句进行更多的匹配。它可以让您构建匹配器循环,就像我做的那样,并大大简化了许多交互问题。看在上帝的份上,尽量避免嵌套代码!程序已经够难了,但又不会使它们变得特别复杂!

计算的一个深刻事实是,只要环境发生变化,在自己的机器上正常运行的简单程序就会失败(而web服务器是另一种环境)。编写代码以适应需要更多的工作-虽然在本例中没有太多-并且意味着它不会在您不期望的情况下突然中断。感谢代码片段@donal。是的,这些环境很难处理。您能帮助我理解带有{.*\n}的独立expect块吗exp_continue part?match regex上要更改的内容看起来像是,它现在不工作了,日志-日志帮助很大!看看它,你真的在寻找文本
{master:1}
?如果你在寻找特定的内容,那么让expect工作就容易多了。(我们需要移动模式以提取模式上方的真实数据,以匹配提示;匹配顺序)。核心问题是,由于时间差异(超出我们的控制),我们在匹配缓冲区中一次获得多行。我尝试在{master:1}之前匹配字符串,基本上是在之前匹配字符串{.所以,如果已经创建了用户类,那么show commad将输出一些东西,如果没有,它将返回空的,因此我尝试在{之前放置/匹配东西,并将其存储在px变量中。我也尝试过在regex下面,但似乎没有一个起作用:(
set found[regexp{.$cmd\r\n(.*login user rancid class remote backup)\s+\r\n\{.*}$value match px]

找到集合[regexp{.*.*rancid\s+\r\n\{.*}$value match px]
好的,我不太确定如何确定您是否找到了任何内容,因为我不知道匹配的格式…但我很确定如何提取您关心的数据。假设您关心的行末尾没有空格。接下来的问题只是确定字符串何时匹配,以及而不是如何说服路由器告诉你这些信息。