HalNineThousand has asked for the wisdom of the Perl Monks concerning the following question:

This is one of those things I've done before and the basics seem simple, but I must be screwing up on something obvious. I've been over the docs on CPAN a number of times. I've used Expect to read from a modem and, years ago, to control a process. Now it won't work for me at all.

I'm testing it on telnet, where I telnet to a system I have set up that doesn't need a username or password, use 'ls', then log out, and even that is not working.

Here's my code:

#!/usr/bin/perl use Expect; our $abi; $res = open_telnet(); if ($res) { print "Failure. Error message: $res\n"; exit; } telnetcmd("ls"); telnetcmd("exit"); exit; sub open_telnet { my ($cmd, $res, $before, @parm); $cmd = "telnet wogglebug"; $abi = Expect->new(); $abi = Expect->spawn($cmd) or die "Can't do expect'"; $res = $abi->expect(5, "/ #", "not known"); if ($res == 1) { return 0; } $before = $abi->before(); if (!$before) { $before = "telnet failed. No reason given"; } return $before; } sub telnetcmd { my ($cmd, $res); $cmd = shift(@_); # print $abi "$cmd\n" or die "Can't write to expect object"; $abi->send("$cmd\n") or die "Can't send to expect object: $abi->er +ror()"; $res = $abi->after(); print "-----------\nAfter: $res\n----------\n"; return $res; }

If I run this as it is, then I always get an error on the 4th line of the telnetcmd routine: "Can't send to expect object: Expect=GLOB(0x8eb92e8)->error() at /threshNet/bin/xm-test line 41." Okay, the obvious is to just use the line before it, the commented out one that prints the command to the process, but even when I do that, I don't get output from the process, either by watching it as it runs, or by using expect->after().

This is just testing, I'm working on controlling another program with Expect, and it seemed to need to use Expect->send_slow() to send commands to that program, so I feel I'll need send() or send_slow() to make it work. But it seems like I must be doing something so obvious I can't find the problem.

There are also a number of other calls to the Expect object that I can't get to work. Expect->pid() doesn't return anything. Except->clear_accum() won't clear the data already in the buffer and Except->before() always returns the data from my first Except->before() call, no matter how many times I've called it.

Any help is appreciated. I suspect once someone points out what I did wrong, I'll be doing a *facedesk* in disbelief I missed something I should have known.

Replies are listed 'Best First'.
Re: Expect Issues
by roboticus (Chancellor) on Dec 31, 2010 at 14:25 UTC

    Hal9K:

    I don't know what's wrong with Expect, but if you change:

    $abi->send("$cmd\n") or die "Can't send to expect object: $abi->error( +)";

    to:

    $abi->send("$cmd\n") or die "Can't send to expect object: " . $abi->er +ror();

    you may get a better error message than:

    Can't send to expect object: Expect=GLOB(0x8eb92e8)->error() at /thres +hNet/bin/xm-test line 41.

    As it stands right now, it's converting $abi into a string, without calling the error() member, so you're not getting a useful error message right now.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      Okay, I see. Thanks, since that helped me understand that whole situation. I'm getting an actual error message now (just the number 0), which supposedly represents the last item returned. Not very helpful, but that's because of Expect not documenting itself well.

Re: Expect Issues
by roboticus (Chancellor) on Dec 31, 2010 at 14:53 UTC

    HalNineThousand:

    I was just looking at the Expect documentation, and the example looks different that your code. They didn't use new() to create the Expect object, instead they used spawn(). Also, they use spawn differently than you do. They have the command and arguments separated. So I think you should try changing the first few lines of your open_telnet subroutine to the following, and see if it helps.

    sub open_telnet { my (@cmd, $res, $before, @parm); @cmd = ("telnet", "wogglebug"); $abi = Expect->spawn(@cmd) or die "Can't do expect'"; $res = $abi->expect(5, "/ #", "not known");

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      roboticus, I should have included this. I tried that -- using the arguments separately, but it never seemed to work, at least not with the other program, so I left it that way with telnet when I tested. I found a number of examples and every example I found gave the command and arguments as just one string. But somehow it seems to work now -- doesn't seem to make a difference.

      Thanks for picking up on that. It's probably several errors like that, all together, that are creating the problem.

Re: Expect Issues
by HalNineThousand (Beadle) on Dec 31, 2010 at 20:44 UTC

    I've got a working version. I'm still not clear on what I did with this that was different from the original, but I went back and wrote it from scratch (I didn't mention that I started with a version that almost worked, then stopped). I didn't copy or paste ANYTHING from the original, I started without sub routines and wrote a simple test, then broke it down into subroutines and got it working. I'll be looking through my old code to see the mistakes once I get time. Here's the working version:

    #!/usr/bin/perl use Expect; our $abi; setup(); sendcmd(); sub setup { $cmd = "telnet wogglebug"; $abi = Expect->new(); $abi->spawn($cmd); $res = $abi->expect(5, "/ #", "not known"); print "Result: $res\n"; if ($res != 1) { print "Failure to open process.\n"; exit; } $before = $abi->before(); show("Before", $before); $after = $abi->after(); show("After", $after); $abi->clear_accum(); return; } sub sendcmd { $abi->send("ls\n"); # print $abi "ls\n"; $before = $abi->before(); $after = $abi->after(); $res = $abi->expect(10, "/ #"); show("Before command", $before); show("After command", $after); show("Result", $res); return; } sub show { my ($msg, $data) = @_; print "-----------------------\n$msg: $data\n--------------------- +--\n"; return; }

    Thanks for the help and when I see what it was that messed up the first version, I'll post it.