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

I have a device that does not support many connections. If it times out during a telnet session, I'm forced to re-cycle the unit. I am using Expect.pm and just snagged the example code in it's perldoc. Normally, the timeout would not be a problem but it is because this device is not a workstation. Here is the output I see
Escape character is '^]'. Ubuntu 8.04.1 scriptbed login: $VAR1 = bless( \*Symbol::GEN0, 'Expect' ); scriptbed Password: $VAR1 = [ bless( \*Symbol::GEN0, 'Expect' ) ]; Can't call method "do_soft_close" on unblessed reference at ./myexpect +.pl line 57.
Here is the full code
#!/usr/bin/perl -w 2 3 BEGIN { 4 unshift(@INC,'/n/home5/release/Perl/Modules/lib/perl5/site_perl/5. +8.0'); 5 } 6 7 use strict; 8 use Expect; 9 use Data::Dumper; 10 11 my $timeout = 1; 12 13 my $username = 'scriptbed'; 14 my $password = 'invalid'; # forcing the timeout 15 16 print localtime(time)."\n"; 17 18 my $exp = Expect->spawn('/usr/bin/telnet','scriptbed'); 19 20 my $spawn_ok; 21 $exp->expect($timeout, 22 [ 23 qr'login: $', 24 sub { 25 $spawn_ok = 1; 26 my $fh = shift; 27 print Dumper $fh; 28 $fh->send("$username\n"); 29 exp_continue; 30 } 31 ], 32 [ 33 'Password: $', 34 sub { 35 my $fh = shift; 36 print $fh "$password\n"; 37 exp_continue; 38 } 39 ], 40 [ 41 eof => 42 sub { 43 my $fh = shift; 44 $fh->do_soft_close(); 45 if ($spawn_ok) { 46 die "ERROR: premature EOF in login.\n"; 47 } else { 48 die "ERROR: could not spawn telnet.\n"; 49 } 50 } 51 ], 52 [ 53 timeout => 54 sub { 55 my $fh = shift; 56 print Dumper $fh; 57 $fh->do_soft_close(); 58 die "Timed out\n"; 59 } 60 ], 61 '-re', qr'[#>:] $', #' wait for shell prompt, then +exit expec t 62 );
  • Comment on Trying to close Expect.pm telnet timeout situation to avoid overwhelming a small target device
  • Select or Download Code

Replies are listed 'Best First'.
Re: Trying to close Expect.pm telnet timeout situation to avoid overwhelming a small target device
by almut (Canon) on Nov 25, 2008 at 02:28 UTC
    $VAR1 = [ bless( \*Symbol::GEN0, 'Expect' ) ];

    As it looks, your $fh (line 55-57) is an arrayref of objects (don't know why)... which would explain the "Can't call method ... on unblessed reference" (because the arrayref is unblessed).  In other words, you might try

    $fh->[0]->do_soft_close();
      I believe the $VAR1 = around the object is a artifact of Dump::Dumper.

        I believe you are wrong (or at least the [] is important as almut suggests):

        use Data::Dumper; my $blessedBe = bless {}, 'Wibble'; print Dumper $blessedBe; print Dumper [$blessedBe];

        Prints:

        $VAR1 = bless( {}, 'Wibble' ); $VAR1 = [ bless( {}, 'Wibble' ) ];

        Perl reduces RSI - it saves typing

        Sure, the $VAR1 = is an artifact, but not the square brackets... (which indicate that Data::Dumper was given an arrayref).  Compare with your first dump in the line:

        scriptbed login: $VAR1 = bless( \*Symbol::GEN0, 'Expect' );
Re: Trying to close Expect.pm telnet timeout situation to avoid overwhelming a small target device
by oko1 (Deacon) on Nov 25, 2008 at 02:09 UTC

    What I often do, instead of having to guess, is run an "autoexpect" session. This will record your subsequent login/logout session and save it as an Expect script which can then be run to repeat the process. From there, converting it to Perl is trivial.

    I have to note that - annoyingly - "autoexpect" is no longer included in the standard Expect package in my favorite Linux distro (Ubuntu); you need to 1) download the "expect-dev" package, and 2) ungzip and "chmod +x " the 'autoexpect.gz' found there. No idea why they did this... but I'm glad it's still available.


    --
    "Language shapes the way we think, and determines what we can think about."
    -- B. L. Whorf
Re: Trying to close Expect.pm telnet timeout situation to avoid overwhelming a small target device
by gmoque (Acolyte) on Nov 25, 2008 at 01:58 UTC
    I think you should try changing the $timeout to -1 or a bigger number than 1 ... If your timeout is 1 second you probably are not even seeing the prompt. Specially if the device is busy with some other tasks
      Actually, I am trying to force the timeout. I am debugging the timeout case.

      My problem is that sometimes it does time out. When that occurs, my device is hung. I need to have the telnet session close more gracefully.