Comunicación Interactiva con Expect

El módulo Expect mantenido por Roland Giersig trae a Perl las funcionalidades del lenguaje Expect. Para su uso, el módulo requiere los módulos IO::Pty y IO::Stty. El lenguaje Expect es descrito en el libro de Don Libes [4] Exploring Expect. El lenguaje Expect esta escrito en Tcl y es, al mismo tiempo, una extensión de Tcl. Puede encontrar una introducción al lenguaje en http://www6.uniovi.es/tcl/tutorial/index.html (puede encontrar una copia en http://nereida.deioc.ull.es/˜lhp/tcl/tutorial/index.html y alguna información adicional en http://nereida.deioc.ull.es/˜lhp/tcl/).

La mayoría de las shell y lenguajes de script proveen un control limitado sobre los procesos: podemos arrancarlos, enviarles señales, etc. En general, no es posible ejecutar en lotes ciertos programas como passwd o ssh. Expect extiende el modelo UNIX de comunicación entre procesos considerando un nivel más de interacción.

Expect fue diseñado para automatizar el manejo de programas interactivos. Un programador Expect escribe un guión describiendo el diálogo entre el usuario y la aplicación. A continuación es posible ejecutar el programa Expect de manera que el papel del usuario queda automatizado. Incluso es posible pasar dinámicamente control del programa al teclado y viceversa. Puede encontrar unos apuntes sobre el uso de expect en http://www.linuxlots.com/˜barreiro/spain/expect/.

Casiano Rodríguez León
2010-03-22
" SRC="ggoogle.gif" ALT="google">etsiiullpcgull
Sig: Práctica: Conexión ssh Sup: Expect Ant: Una Introducción a Expect
Casiano Rodríguez León
2010-04-20
os de $delay segundos.

El Método print

Mediante llamadas a print en el manejador de la seudoterminal $rsh proporcionamos la entrada al comando lanzado.

El Método any de List::MoreUtils

Si la máquina de la red interna a la que entramos requiere una validación adicional (esta entre las descritas en el array @MOREPASSWORDS) la (misma) clave es introducida de nuevo.

El Método interact

El método interact (línea 50) devuelve el control de la entrada/salida a los manejadores de fichero habituales STDIN, STDOUT y STDERR.

Ejercicio 8.2.1   Estudie la siguiente cuestion (Module Net::SSH::Expect - Cannot interact) en PerlMonks. ¿Cuales son sus sugerencias?



Subsecciones
Casiano Rodríguez León
2010-05-05
my $read = sysread(STDIN, $char, 1); 259 last WHILE_NOT_ESCAPE_OR_EOF if $char eq $escape; 260 if (defined $read && $read) { 261 syswrite($pty,$char,$read); 262 } 263 else { 264 last WHILE_NOT_ESCAPE_OR_EOF 265 } 266 } 267 } 268 redo; 269 } 270 return $return_value; 271 } 272 273 sub deadline { 274 ${$_[0]->{deadline}} = $_[1] if @_ >1; 275 ${$_[0]->{deadline}}; 276 } 277 278 sub parenthesis { 279 return @{$_[0]->{parenthesis}}; 280 } 281 282 sub can_read { 283 my $self = shift; 284 my $deadline = shift; 285 my $sel = $self->{sel}; 286 287 return $sel->can_read($deadline); 288 } 289 290 sub can_write { 291 my $self = shift; 292 my $deadline = shift; 293 my $sel = $self->{sel}; 294 295 return $sel->can_write($deadline); 296 } 297 298 sub AUTOLOAD { 299 my $self = shift; 300 301 $AUTOLOAD =~ /.*::(\w+)/; 302 my $subname = $1; 303 carp "No such method $AUTOLOAD " unless (defined($subname)); 304 no strict 'refs'; 305 if (exists($self->{$subname})) { 306 *{$AUTOLOAD} = sub { 307 $_[0]->{$subname} = $_[1] if @_ >1; 308 $_[0]->{$subname} 309 }; 310 $self->{$subname} = $_[0] if @_; 311 return $self->{$subname}; 312 } 313 carp "No such method $AUTOLOAD"; 314 } 315 316 sub DESTROY { 317 } 318 319 1;

Veamos un ejemplo de uso:

lhp@nereida:~/Lperl/src/perl_networking/ch2/IO-Pty-Script/script$ cat -n ptyconnect4.pl
 1  #!/usr/bin/perl -sw -I../lib
 2  use strict;
 3  use IO::Pty::Script qw{TIMEOUT DEFAULT_DEADLINE chats};
 4
 5  my %script;
 6  our($c, $d, $p, $f); # Inicializadas via -s switch
 7
 8  $p = '' unless defined($p);
 9  $d = DEFAULT_DEADLINE unless defined($d);
10  $f = '' unless defined($f);
11  die "Usage:$0 -c=command -p=key -d=deadline -f=script\n"
12                                        unless defined($c);
13  my $prompt = '[$>]\s+';
14
15  $script{'ssh -l casiano etsii'} = [
16  '.*password:\s'           => "$p\n",
17  '(word:\s)|(login: )|(> )' => "$f\n",
18  $prompt                    => "exit\n"
19  ];
20
21  #$script{'ssh -l casiano etsii'} = [
22  #'.*password:\s'           => "$p\n",
23  #'.*q para salir.\s\s\s\s' => "millo\n",
24  #'word:\s'                 => "$p\n",
25  #'(word:\s)|(login: )|(> )' => "$f\n",
26  #$prompt                    => "exit\n"
27  #];
28
29  $script{'ssh -l casiano beowulf'} = [
30  '.*password:\s'           => "$p\n",
31  $prompt                   => "$f\n",
32  $prompt                   => "exit\n"
33  ];
34
35  #$script{'ssh europa'} = [
36  #$prompt                   => "$f\n",
37  #$prompt                   => [\&titi, 1, 2, "tres"],
38  #$prompt                   => "exit\n"
39  #];
40
41  $script{'ssh europa'} = [
42  $prompt                   => "$f\n",
43  $prompt                   => [\&titi, 1, 2, "tres"],
44  $prompt                   => sub { my $self = shift; $self->keyboard("\cD"); "ls\n" },
45  $prompt                   => "echo 'Despues de la interaccion'\n",
46  $prompt                   => "exit\n"
47  ];
48
49  sub tutu {
50    print "<<sub tutu:\n";
51    print $_[0];
52    my @par = $_[0]->parenthesis();
53    print "Paréntesis: @par\n";
54    print "Es posible leer en la terminal\n" if $_[0]->can_read(TIMEOUT);
55    print "Es posible escribir en la terminal\n" if $_[0]->can_write(TIMEOUT);
56    print "end sub tutu>>\n";
57    "8*2\n"
58  }
59
60  sub titi {
61    local $" = "\nsub titi:";
62    print "<<sub titi: @_>>\n";
63    "date\n";
64  }
65
66  $script{bc} = [
67  'warranty..\s\s' => "5*9.5\n",
68  '(\d+)\.?(\d*)\s+' => \&tutu,
69  '\d+\.?\d*\s+' => "4*2\n",
70  '\d+\.?\d*\s+' => "quit",
71  ];
72
73  my $bc = IO::Pty::Script->new(
74            command => 'bc',
75            deadline => 4,
76            script => $script{bc},
77            defaultaction => sub { print $_[0] }
78          );
79
80  my $s = IO::Pty::Script->new(
81            command => $c,
82            deadline => $d,
83            script => $script{$c},
84            defaultaction => sub { print $_[0] }
85          );
86  chats($bc, $s);

Sigue un ejemplo de ejecución:

lhp@nereida:~/Lperl/src/perl_networking/ch2/IO-Pty-Script/script$ ptyconnect4.pl -c='ssh -l casiano beowulf' -p=password -d=3 -f='ls'
<<r = 'bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
'
s = ''
d = '0'>>
<<sub tutu:
<<r = '47.5
'
s = ''
d = '0'>>
Paréntesis: 47 5
Es posible escribir en la terminal
end sub tutu>>
<<r = '16
'
s = ''
d = '0'>>
<<r = '8
'
s = ''
d = '0'>>
<<r = 'casiano@beowulf's password: '
s = ''
d = '0'>>
<<r = '
Linux beowulf 2.6.15-1-686 #2 Mon Mar 6 15:27:08 UTC 2006 i686

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Mon Jun  5 13:24:42 2006 from nereida.deioc.ull.es
casiano@beowulf:~$ '
s = ''
d = '0'>>
<<r = 'bc_pty2.pl  _Inline  passwd_pty.pl  pilock.pl  src         try6
bc_pty6.pl  log      pi             pi.pl      ssh_pty.pl
casiano@beowulf:~$ '
s = ''
d = '0'>>
lhp@nereida:~/Lperl/src/perl_networking/ch2/IO-Pty-Script/script$



Subsecciones
Casiano Rodríguez León
2011-04-11