0

I'm trying to understand the Expect Perl module.

I want to take the value and the machine from $var, but I couldn't make my code work even if I used regular expressions.

I want to take from $var the machine and the value from the command prompt (like machine 1 - 7) but I don't know why it prints $var in the terminal as I didn't call the $var variable

$Expect::Exp_Internal =0;
my $admin_user = "root";
my $timeout = 40;
my $prompt = '~]#';


my @devices =qw(
machine1
machine2
machine3);


foreach my $device (@devices){
my $exp = Expect->spawn("ssh", "-o", "UserKnownHostsFile /dev/null", "root\@$device");

$exp->log_user(0);


my $seen_user = 0;


$exp->expect(
    $timeout,
    [
        qr/connecting \(yes\/no\)\? / => sub {
            my $self = shift;
            $self->send("yes\r");
            exp_continue;
        }
    ],
    [
        qr/User: ?/ => sub {
            my $self = shift;
            if ( $seen_user == 1 ) {
                $var .= "Bad password on $device \n<br>";
                $exp->soft_close();
            }
            #  $self->send("$admin_user\n<br>");
            $seen_user = 1;
            exp_continue;
        }
    ],
    [
        qr/$prompt/ => sub {
            my $self = shift;
            #    print 'first_prompt';
        }
    ],
    [
        'timeout' => sub {
            $var .= "timed out during login on $device\n<br>";
        }
    ]
);

$exp->log_user(1);

# This following line is printed, without being called:

my $var = $exp->send("ps -aef | grep -i app | wc -l\n");

#$var =~ s/\D+//g;
#print 'numbers'.$var;

print $var;
undef $var;

my $logout_sent = 0;

$exp->expect(
    $timeout,
    [
        qr/$prompt/ => sub {
            my $self = shift;
            $exp->log_user(0);
            # $self->send("ps -aef | grep -i sql | wc -l\r");
            $self->send("logout\r");
            $logout_sent = 1;
            exp_continue;
        }
    ],

    }],

    [
        qr/\(y\/N\)/ => sub {
            my $self = shift;
            $self->send("y");
            print "ok\n<br>";
            #    exit 0;
        }
    ],
    [
        'timeout' => sub {
            print "timed out waiting for prompt\n<br>";
            # exit 1;
        }
    ],
    [
        'eof' => sub {
            if ($logout_sent) {
                $var .= "succesfully logged out from the $device\n<br>";
                #exit 0;
            }
            else {
                $var .="unexpected eof waiting for prompt on $device\n<br>";
            }
        }
    ]
);

}

The Output

<br>ps -aef | grep -i app | wc -l
7
[root@machine1 ~]# succesfully logged out from the machine1
<br>ps -aef | grep -i app | wc -l
9
[root@machine2 ~]# succesfully logged out from the machine2
<br>ps -aef | grep -i app | wc -l
7
[root@machine3 ~]# succesfully logged out from the machine3

6
  • 1
    I've tidied your Perl code so that I could understand it. You should carefully indent anything you that you write, at least so that you can read it yourself, but especially if you are asking for help with it. The code you show doesn't even compile, so it certainly doesn't produce the output that you say it does. There is no point at all in posting code that behaves differently from the version you are having trouble with: we cannot possibly help you to fix an imaginary program. You should study How to create a Minimal, Complete, and Verifiable example. Commented Sep 3, 2018 at 20:32
  • It is very hard to tell what the real output from your code is. You have enclosed some HTML output within in an <i> element, and Stack Overflow has formatted the resulting text. There is specific provision for posting text data of any sort: you simply add the data you want to show into your post and indent it all by four spaces. You can select the data and use Ctrl-K to achieve this, or you can click on the { } icon to do the same thing. All of this is explained in Editing help which is linked on the tool bar above every edit window. Commented Sep 3, 2018 at 20:39
  • What do you mean by "This following line is printed, without being called:". Are you saying that my $var = $exp->send("ps -aef | grep -i app | wc -l\n") appears on the console, but ps, grep, and wc aren't run? That seems very unlikely. Commented Sep 3, 2018 at 20:44
  • Hi Borodin, thank you for helping, I added the variable definition and the for loop to have the code exactly as I am compiling it. I did italic for the output to emphasize what I have in the console after I execute the script. I don't understand why is showing in the console that variable, and my feeling is that send function in the Expect module is not very documented and probably I miss some bits Commented Sep 4, 2018 at 10:38
  • 1
    @AndreiVieru You might have to turn off terminal echo using $exp->slave->stty( '-echo' ) before you spawn the ssh. This requires the IO::Stty module. Commented Sep 4, 2018 at 12:58

1 Answer 1

0

You can get the value of the machine like this:

# $exp->clear_accum(); # clear the accumulator if you need to
$exp->expect( $timeout, '-re', 'root@machine\d+');
my ($machine_number) = $exp->match() =~ /root@machine(\d+)/;

Then you can get the number of processes like this:

$exp->clear_accum(); # clear the accumulator if you need to
$exp->send("ps -aef | grep -i app | wc -l\n");
$exp->expect( $timeout, '-re', '^\d+');
my ($num_processes) = $exp->match() =~ /(\d+)/;
Sign up to request clarification or add additional context in comments.

1 Comment

I'm sorry to down vote your answer, but the question itself is still in doubt, and if you want to provide a solution to a half-formed question then you need to specify the interpretation that you are solving. You have also posted unexplained code, and so diminished even the chance that others will benefit from this page.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.