Usando Callbacks

lhp@nereida:~/Lperl/src/expect/tutorial$ cat -n callbacks
 1  #!/usr/bin/perl -w
 2  use strict;
 3  use Expect;
 4
 5  # $Expect::Debug=2;
 6  $Expect::Exp_Internal=1;
 7
 8  # Get the password.
 9  sub Expect::get_password {
10    my $stdin = shift;
11
12    $| = 1;
13    print "Enter password: ";
14    $stdin->exp_stty('-echo'); # Now turn off echoing
15    my ($match_num,$error,$match,$before,$after)=$stdin->expect(undef,"\n");
16    my $password = $before;
17    $stdin->exp_stty('echo'); # Turn echo back on
18    print "\n"; # print that newline that wasn't echoed
19    return $password;
20  }
21
22  my $timeout = 10;
23  my $RSH=`which ssh`; chomp($RSH);
24  my $host_to_login_to= shift || 'localhost';
25  my $stdin=Expect->exp_init(\*STDIN);
26  my $username = shift || `whoami`;
27  my $password =  $stdin->get_password();
28  my $prompt = qr'[$>#:] $';
29  my $spawn_ok;
30
31  sub login_handler {
32    my $self = shift;
33    $spawn_ok = 1;
34    print $self "$username\n";
35    exp_continue;
36  }
37
38  sub password_handler {
39    my $self = shift;
40    $spawn_ok = 1;
41    print $self "$password\n";
42    exp_continue;
43  }
44
45  sub eof_handler {
46    my $self = shift;
47    die "Error! Premature EOF during login\n" if $spawn_ok;
48    die "Error! Could not spawn ssh\n";
49  }
50
51  ### main
52
53  #$stdin->stty(qw(raw -echo));
54  my $ssh = Expect->spawn($RSH, $host_to_login_to) or die "Cannot spawn ssh: $!\n";
55
56  $ssh->expect(
57    $timeout,
58    [qr'login: $', \&login_handler],
59    ['Password: ', \&password_handler],
60    ['eof',        \&eof_handler],
61    ['timeout',    sub { die "No login.\n"; }],
62    '-re', $prompt, # wait for shell prompt then exit expect
63  );
64
65  print $ssh "uname -a\n"; $ssh->expect($timeout, '-re', $prompt);
66  print $ssh "bc\n";       $ssh->expect($timeout, '-re', '.+');
67  print $ssh "4*8\n";      $ssh->expect($timeout, '-re', '\d+\*\d+\s+\d+');
68  my $result = $ssh->match();
69  print $ssh "quit\n";      $ssh->expect($timeout, '-re', $prompt);
70
71  $ssh->hard_close();
72  $stdin->stty(qw(sane));
73
74  $result =~ s/[\r\n]/=/g;
75  print "\nRemote Machine Result: $result\n";
76
77  =head1 NAME callbacks
78
79  =head1 SYNOPSIS
80
81    callbacks [machine [username]]
82
83  =head1 DESRIPTION
84
85  Example illustrating the use of the Expect.pm module.
86  Makes a ssh connection to C<machine> as C<username>.
87  Ask for the pass and send it using C<Expect>. Sends
88  a C<uname> command and closes the session.
89
90  Follows an example of use of this script.
91
92    lhp@nereida:~/Lperl/src/expect/tutorial$ ./callbacks europa pp2
93    Enter password:
94    Linux europa.xxxx.xxx.es 2.4.20-ck2 #1 vie mar 28 17:32:02 WET 2003 i686 unknown
95
96    Most of the programs included with the Debian GNU/Linux system are
97    freely redistributable; the exact distribution terms for each program
98    are described in the individual files in /usr/share/doc/*/copyright
99
100    Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
101    permitted by applicable law.
102    You have mail.
103    Last login: Wed Mar 15 10:09:39 2006 from nereida.xxxx.xxx.es
104    lhp@europa:~$ lhp@nereida:~/Lperl/src/expect/tutorial$
La llamada de la línea 56 en este ejemplo tiene un formato diferente. Sigue el esquema:
$exp->expect(
   $timeout,
   [ qr/regexp1/i, sub { my $self = shift; ... exp_continue; }, @optional_subparams],
   [ qr/regexp2/i, sub { my $self = shift; ... exp_continue; }, @optional_subparams],
   [ qr/regexp3/i, sub { my $self = shift; ... exp_continue_timeout; }, @optional_subparams],
   .................................................................................
   [ 'eof',        sub { my $self = shift; ... exp_continue; }, @optional_subparams],
   [ 'timeout',    sub { my $self = shift; ... exp_continue; }, @optional_subparams],
   $shell_prompt);
Esto es, una especificación de un patrón viene dada por el esquema

[ $regexp, sub { ... }, @optional_subparams]

Cuando el patrón casa se llama a la subrutina con parámetros ($matched_expect_obj, @optional_subparms). La subrutina puede retornar el símbolo exp_continue para continuar con el casamiento de patrones reinicializando el reloj o bien exp_continue_timeout para continuar sin reiniciarlo.

Casiano Rodríguez León
Licencia de Creative Commons
Programación Distribuida y Mejora del Rendimiento
por Casiano Rodríguez León is licensed under a Creative Commons Reconocimiento 3.0 Unported License.

Permissions beyond the scope of this license may be available at http://campusvirtual.ull.es/ocw/course/view.php?id=44.
2012-06-19