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

Andrei Vieru
  • 154
  • 1
  • 11
  • 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*](http://stackoverflow.com/help/mcve). – Borodin Sep 03 '18 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 `` 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*](https://stackoverflow.com/editing-help) which is linked on the tool bar above every edit window. – Borodin Sep 03 '18 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. – Borodin Sep 03 '18 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 – Andrei Vieru Sep 04 '18 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. – Håkon Hægland Sep 04 '18 at 12:58
  • @AndreiVieru: *"I did italic for the output to emphasize what I have in the console after I execute the script"* Italic is inappropriate for either data or code. There is a specific markup standard for both embedded in Stack Overflow and you should use it. Please study [***Markdown help***](https://stackoverflow.com/editing-help) and apply it carefully. I have done my best to improve your question, but only you can edit it to represent your situation accurately. – Borodin Sep 05 '18 at 18:22

1 Answers1

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+)/;
Håkon Hægland
  • 39,012
  • 21
  • 81
  • 174
  • 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. – Borodin Sep 05 '18 at 18:26