【问题标题】:expect_out(buffer) not capturing all the data while being called via php通过 php 调用时,expect_out(buffer) 未捕获所有数据
【发布时间】:2019-07-03 17:33:15
【问题描述】:

我正在尝试通过期望脚本从交换机获取配置详细信息。
当我通过 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(buffer),

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 调用脚本时,缓冲区没有所有命令输出并且匹配失败。
谁能指导我可能是什么错误。谢谢。

【问题讨论】:

    标签: php tcl expect


    【解决方案1】:

    为什么会有不同?嗯,有各种可能的原因。不同的时间可以是其中之一;这是非常可能并且非常难以预防。您只需编写代码以适应变化;幸运的是,这相当容易。

    一般来说,不建议使用$expect_out(buffer) 本身,因为它没有定义了其中累积了多少数据。它可能具有匹配expected 模式所需的数量,但实际上并不能保证匹配更多。我希望脚本更像这样:

    #!/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
    }
    

    一般来说,您应该尝试构建您的代码,以便将您的expects 和sends 交错,尽管连续几个expects 的序列是可以的。但是,您可以把它想象成 send 直到下一个 expect 才真正被处理。

    注意exp_continue 的使用。这是 Expect 的一个非常强大的功能,它可以让您保持当前的 expect 语句进行更多匹配。它使您可以构建匹配器循环,例如我所做的那样,并大大简化了许多交互问题。看在上帝的份上,尽量避免嵌套代码!程序足够难而不会使它们变得特别复杂!

    【讨论】:

    • 计算的一个深刻真理是,当环境发生变化时,在您自己的机器上运行的简单程序可能会在环境发生变化时失败(而 Web 服务器是不同的环境)。编写代码以适应需要更多的工作——尽管在这种情况下不会更多——这意味着它不会在你意想不到的时候突然中断。
    • 感谢代码 sn-p @donal。是的,这些环境很难处理。您能帮我理解带有 {.*\n} 和 exp_continue 部分的单独期望块吗?匹配正则表达式的某些内容看起来像,它现在不起作用,日志 - filebin.net/3wr14jj21rbk70n5
    • 日志有很大帮助! 看看它,你真的在​​寻找文字{master:1}吗?如果您正在寻找特定的东西,那么让期望工作更容易。 (我们需要移动模式以提取模式上方的真实数据以匹配提示;匹配的顺序很重要。)核心问题是由于时间差异(我们无法控制)我们'在匹配缓冲区中一次获取多行。
    • 我正在尝试匹配 {master:1} 之前的字符串,基本上是 { 之前的字符串。因此,如果已经创建了用户类,那么 show commad 会输出一些东西,如果不是,它会回复空,因此我试图在该 { 之前放置/匹配东西,并将其存储在 px 变量中。我也试过下面的正则表达式,但似乎没有一个工作:(
      set found [regexp { .*$cmd\s+\r\n(.*login user rancid class remote-backup)\s+\r\n\{.*} $value match px ]
      set found [regexp { .*rancid\s+\r\n\{.*} $value match px ]
    • 好的,我不太确定如何确定您是否找到任何东西,因为我不知道与那里匹配的格式......但我很确定如何提取您关心的数据。假设您关心的行尾没有空格。剩下的问题就是决定何时匹配字符串,而不是如何说服路由器告诉你信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-21
    • 1970-01-01
    • 2014-12-04
    • 2013-12-27
    • 2012-04-11
    • 1970-01-01
    相关资源
    最近更新 更多