Expect_out(buffer)在通过php调用时未捕获所有数据

时间:2019-07-03 17:33:15

标签: php tcl expect

我正在尝试通过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调用的脚本时,缓冲区没有输出所有命令,并且匹配失败。
有人可以指导我怎么做。谢谢。

1 个答案:

答案 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
}

通常,您应该尝试对代码进行结构化,以便交错expectsend,尽管连续几个expect序列也可以。但是,您可以将其视为好像send直到下一个expect才真正被处理。

请注意exp_continue的使用。这是Expect的一项非常强大的功能,可让您保持当前的expect语句进行更多匹配。它使您可以构建匹配器循环(例如我所做的循环),并大大简化了许多交互问题。出于善意,请尽量避免嵌套代码!程序足够困难,而且不会使其变得更加复杂!