linuxperlexpect.pm

How do you properly wait for the prompt in the terminal before sending a command using expect for perl?


I'm very new to both Perl and expect and have been trying to figure out how to send a command when only the prompt appears. I know how to send a command after a certain output is displayed in the terminal, but can't find the correct way to send a command when the previous command doesn't have a specific success message, so the only thing on the line after the command is the prompt. The code I tried to use was:

$exp->expect($timeout,  
      [$user."@".$host, sub{my $self = shift;
                               $self -> send(the command I want to send);
                               exp_continue;}],
      $GW);

The $user."@",$host represents the prompt in the terminal, but as you might be able to guess, the command is constantly sent as once the command is sent, the prompt appears again so the command is sent again, so the program gets stuck in an infinite loop. I've tried changing exp_continue to exit, but it meant the whole subroutine stopped working for some reason. I've also tried changing exp_continue to exp_continue_timeout and adding sleep statements in the subroutine, but it didn't stop the infinite loop.

I've also tried using just

sleep(5);
$exp->send(command);

but this just sends the command at seemingly random times and doesn't wait for the previous command to finish. Is this method the only way possible, or is there a method that waits for the prompt to appear but only sends the command once?


Solution

  • If you just want the expect() call to return after your match is found and you do send(), simply return undef instead of exp_continue.

    Usually, you use expect() in your way when you have a lot of different prompts that you want to react to. If you are just going to send commands line by line and have the same prompt between each line you can just alternate them:

    my $prompt = $user."@".$host;
    $rc = $exp->expect($timeout, $prompt);
    $exp->send("date\n");
    $rc = $exp->expect($timeout, $prompt);
    $exp->send("ls\n");
    

    or see also the Expect::Simple module which handles for you looking for the prompt each time.