Home > Net >  Expect.pm:expect() gives "Unexpected Subroutine" error
Expect.pm:expect() gives "Unexpected Subroutine" error

Time:08-25

I'm extremely new to Perl and struggling with something. Recently, another developer left my company, and my boss has asked me to fix a Perl script that my former colleague wrote but did not document. This script worked great in the past. I mostly understand his code, but a call to Expect.pm:expect() confuses me.

The script is meant to scp a file off a remote server. Here's my former colleague's code, slightly abridged:

#!/usr/bin/env perl

# Lots of use statements here, including:
use Expect;

# We set a lot of variables here...

# We use expect->spawn() to spawn an scp session into the remote machine
my $scp_exp = Expect->spawn("scp", "$account\@$remoteIP:$dir/$file", "$local_dir/");

# We set the parity
$scp_exp->raw_pty(1);

# We call expect() for the SCP session
$scp_exp->expect($timeout, [qr/.*[pP]assword:/, \&givePd, $pd],
        [qr/.*[pP]assword: /, \&givePd, $pd],
        [qr/100%/, \&closeExp],
        [qr/No such file or directory/, sub{exp_continue}],
        [qr/$prompt/, \&closeExp]);

Most of this I understand, but that last line ($scp_exp->expect()) is completely baffling to me. I assume that when the script scp's to the remote machine, we have to give expect() a timeout, then prepare expect() for all the possible outputs the remote machine might give? The man page for expect() talks about an array of @matched_patterns, but I don't fully follow that discussion.

When the script runs, I get this exact string as my output:

Password: Undefined subroutine &main::givePd called at /usr/share/perl5/Expect.pm line 759.

I'm assuming that my script executes just fine, but when expect() issues its commands on the remote machine, the "givePd" string confuses the remote host. So expect() throws an error, and everything comes crashing to a halt.

BTW, the only references to string "givePd" are shown in the code excerpt, above. So that's not a variable or something that was improperly set.

There's one more thing I should mention. I am trying to run my colleague's script on a new Ubuntu machine, a machine that has never successfully run this script before. In fact, when I ran the script for the first time, I realized that I needed to use apt-get install to install the Expect.pm module:

sudo apt-get install -y libexpect-perl

So I guess its possible I installed a newer version of the module? Not sure.

Anyone see where I am going wrong?

CodePudding user response:

\&givePd produces a reference to the sub givePd. This is passed to expect to tell it to call givePd when certain strings are received from the child program. But just like the message says, and just like you said in your answer, you never defined givePd. (Same for closeExp.) So it's obviously going to fail.

  • Related