$stdin->manual_stty(1)
para hacer que controles como ^Z
suspendan la terminal
local y no la terminal remota.
lhp@nereida:~/Lperl/src/expect/tutorial$ cat -n etsii_interconnect 1 #!/usr/bin/perl -w 2 use strict; 3 use Expect; 4 5 # $Expect::Debug=2; 6 $Expect::Exp_Internal=1; 7 8 my $RSH='/usr/bin/ssh'; 9 my $host_to_login_to='username@etsii'; 10 my $machine='tomillo'; 11 12 # Get the password. 13 print "Enter password: "; 14 my $stdin=Expect->exp_init(\*STDIN); 15 $stdin->exp_stty('-echo'); # Now turn off echoing 16 my ($match_num,$error,$match,$before,$after)=$stdin->expect(undef,"\n"); 17 my $password = $before; 18 $stdin->exp_stty('echo'); # Turn echo back on 19 print "\n"; # print that newline that wasn't echoed 20 21 my $rsh=Expect->spawn($RSH,$host_to_login_to); 22 23 # Look for a password prompt in the bastion 24 $rsh->expect(30,'-re','word:\s$')||(die"Never got password prompt\n"); 25 print $rsh "$password\r"; 26 27 # Look for machine prompt. 28 $rsh->expect(30,'-re','salir\)(\s)+$')||(die"Never got machine prompt\n"); 29 30 print $rsh "$machine\r"; 31 32 # Look for a password prompt in the new machine. 33 $rsh->expect(30,'-re','word:\s$')||(die"Never got password prompt\n"); 34 print $rsh "$password\r"; 35 36 # Look for a prompt. Prompt can be # $ > or ] followed by a whitespace. 37 my $prompt = '[\]\$\>\#]\s$'; 38 39 # Note the use of -re 40 $rsh->expect(30,'-re',$prompt)||(die "Never got prompt on host\n"); 41 42 # OK, now return control to user. 43 $stdin->manual_stty(1); 44 $stdin->set_group($rsh); 45 Expect::interconnect($stdin, $rsh);
Normalmente, cuando establecemos interacción de STDIN
con un proceso se pone STDIN
en modo raw.
En modo raw
, el texto pasa directamente desde la seudoterminal ( PTY )
al dispositivo terminal ( TTY ). Esto es diferente del modo
cooked en el cuál se hacen cambios a los datos
en su paso del PTY al TTY. Por ejemplo, la aplicación obtiene líneas
de entrada completas y puede enviar un linefeed
cuando requiere
una nueva línea. Además el texto tecleado es devuelto a la pantalla
( echo ). Lo habitual cuando un programa arranca es que,
para facilitar la entrada/salida de texto, la
terminal esté en modo cooked
. Cuando se requiere un mayor control,
como ocurre con las PTY, se comienza en modo raw
.
Cuando hacemos ssh
a la shell en la máquina remota
estamos usando el modo raw
. Si pulsamos
^Z
irá directamente sin ser procesado a la TTY
en la máquina remota. Allí será interpretado y el proceso
suspendido será el que esté ejecutándose en la máquina remota.
La llamada a $stdin->manual_stty(1)
establece que Expect
debe establecer los parámetros de la terminal de manera razonable.
Asi queda desactivado el modo raw
y cuando pulsamos
^Z
suspendemos Expect
:
............ Arrancamos la conexión y ... Matchlist: () Returning from expect successfully. St Security Monitor 3.2 actived /home/username[4]> uname -a uname -a Linux tomillo.remote_machine 2.4.22-1.2188.nptlsmp #1 SMP Wed Apr 21 20:12:56 EDT 2004 i686 i686 i386 GNU/Linux /home/username[5]> ## <-- PULSAMOS ^Z [2]+ Stopped ./etsii_interconnect lhp@nereida:~/Lperl/src/expect/tutorial$ uname -a ## MAQUINA LOCAL Linux nereida.deioc.ull.es 2.4.20-perfctr #6 SMP vie abr 2 18:36:12 WEST 2004 i686 GNU/Linux lhp@nereida:~/Lperl/src/expect/tutorial$ fg # VOLVAMOS CON LA CONEXION ./etsii_interconnect hp@nereida:~/Lperl/src/expect/tutorial$ fg ./etsii_interconnect /home/username[5]> pwd pwd /home/username /home/username[6]> uname -a uname -a Linux tomillo.remote_machine 2.4.22-1.2188.nptlsmp #1 SMP Wed Apr 21 20:12:56 EDT 2004 i686 i686 i386 GNU/Linux ............
Para que este esquema de trabajo funcione debe evitarse
el uso del método interact
. Parece que este método
se empeña en establecer su propio juego de modos que entra
en conflicto con lo que queremos. El método interact
es una macro que llama a interconnect
para conectar
dos procesos. De aqui las dos últimas líneas del código:
44 $stdin->set_group($rsh); 45 Expect::interconnect($stdin, $rsh);
El método interconnect
tiene la sintáxis Expect::interconnect(@objects)
.
Lee desde @objects
(en nuestro ejemplo desde $stdin
y $rsh
)
e imprime en sus @listen_groups
. Esta llamada junto con
la llamada a $stdin->set_group($rsh)
establecen que las escrituras en $stdin
deben ser propagadas
a $rsh
. Por defecto, los miembros de @objects
y sus @listen_groups
se ponen a raw -echo
durante
la interconexión. Al establecer $object->manual_stty()
podemos modificar esta conducta. Los valores originales
del TTY se restauran al finalizar la interconexión.
Casiano Rodríguez León