Conmutando Entre Modo Batch e Interactivo

El siguiente ejemplo muestra como conmutar entre el modo dirigido y el modo interactivo:

pp2@nereida:/tmp$ cat -n remoteinteract.pl
 1  #!/usr/bin/perl -w
 2  # $Id: remoteinteract.pl,v 1.1 2001/03/22 01:44:57 btrott Exp $
 3
 4  ## remoteinteract.pl is an example of using Net::SSH::Perl to communicate
 5  ## interactively with a remote command. In this case, that command is the
 6  ## passwd command.
 7  ##
 8  ## Generally when executing a command that prompts you for information,
 9  ## you need to be interactive to respond to the prompts. Net::SSH::Perl
10  ## allows you to register handlers for specific packet types that are sent
11  ## to your client; in these handlers, you can check for recognizable
12  ## prompts and act accordingly by sending a response (using a STDIN
13  ## packet).
14  ##
15  ## remoteinteract.pl shows you how in an example of changing a password
16  ## using the 'passwd' command. We check for three prompts: the prompt
17  ## for the user's current password, the prompt for the new password, and
18  ## the prompt for confirmation of the new password.
19  ##
20  ## You'll need to set the variables $host, $username, $new_password, and
21  ## $old_password.
22  ##
23  ## Remember that this is just an example and should not be used without
24  ## the addition of better error checking.
25
26  my($host, $username, $new_password, $old_password)
27    = ('------------------', '--------', '---------', '--------');
28
29  use strict;
30  use Net::SSH::Perl;
31
32  ## We need to import the Constants module because we need the constant
33  ## for the SSH_SMSG_STDERR_DATA and SSH_CMSG_STDIN_DATA packet types.
34  ## Importing the :msg tag imports all of the SSH_xMSG constants.
35  ##
36  ## If we just wanted to import constants for the above two packet types,
37  ## we could use this instead:
38  ##
39  ##     use Net::SSH::Perl::Constants qw(
40  ##         SSH_SMSG_STDERR_DATA SSH_CMSG_STDIN_DATA
41  ##     );
42  ##
43  ## It's more verbose, certainly, but it does cut down on the number of
44  ## constants imported into our package.
45
46  use Net::SSH::Perl::Constants qw( :msg );
47
48  ## Create a Net::SSH::Perl object and login to the remote host.
49
50  my $ssh = Net::SSH::Perl->new($host, debug => 1);
51  $ssh->login($username, $old_password);
52
53  ## Register a handler routine for packets of type SSH_SMSG_STDERR_DATA.
54  ## This routine will be called whenever the client loop (in
55  ## Net::SSH::Perl) receives packets of this type. It will be given
56  ## two arguments: the Net::SSH::Perl object, and the Net::SSH::Perl::Packet
57  ## object that was received.
58  ##
59  ## We use get_str to get the contents of the STDERR message (because
60  ## passwd writes its prompts to STDERR), then check those against the
61  ## interactive prompts we expect.
62  ##
63  ## For each prompt, we send a packet of STDIN data, which is our response
64  ## to the prompt. For example, when prompted for our current password,
65  ## we send a packet containing that current password.
66  ##
67  ## NOTE: this does not include error checking, and thus should not be
68  ## used wholesale.
69
70  $ssh->register_handler(SSH_SMSG_STDERR_DATA, sub {
71      my($ssh, $packet) = @_;
72      my $str = $packet->get_str;
73
74      if ($str eq "(current) UNIX password: ") {
75          my $packet = $ssh->packet_start(SSH_CMSG_STDIN_DATA);
76          $packet->put_str($old_password);
77          $packet->send;
78      }
79
80      elsif ($str eq "New UNIX password: ") {
81          my $packet = $ssh->packet_start(SSH_CMSG_STDIN_DATA);
82          $packet->put_str($new_password);
83          $packet->send;
84      }
85
86      elsif ($str eq "Retype new UNIX password: ") {
87          my $packet = $ssh->packet_start(SSH_CMSG_STDIN_DATA);
88          $packet->put_str($new_password);
89          $packet->send;
90      }
91  });
92
93  ## After registering the handler, we run the command.
94
95  $ssh->cmd('passwd');

Véase un ejemplo de ejecución:

pp2@nereida:/tmp$ remoteinteract.pl
local.host: Reading configuration data /home/pp2/.ssh/config
local.host: Reading configuration data /etc/ssh_config
local.host: Connecting to some.remote.host, port 22.
local.host: Remote version string: SSH-2.0-OpenSSH_4.7p1 Debian-9

local.host: Remote protocol version 2.0, remote software version OpenSSH_4.7p1 Debian-9
local.host: Net::SSH::Perl Version 1.30, protocol version 2.0.
local.host: No compat match: OpenSSH_4.7p1 Debian-9.
local.host: Connection established.
local.host: Sent key-exchange init (KEXINIT), wait response.
local.host: Algorithms, c->s: 3des-cbc hmac-sha1 none
local.host: Algorithms, s->c: 3des-cbc hmac-sha1 none
local.host: Entering Diffie-Hellman Group 1 key exchange.
local.host: Sent DH public key, waiting for reply.
local.host: Received host key, type 'ssh-dss'.
local.host: Host 'some.remote.host' is known and matches the host key.
local.host: Computing shared secret key.
local.host: Verifying server signature.
local.host: Waiting for NEWKEYS message.
local.host: Enabling incoming encryption/MAC/compression.
local.host: Send NEWKEYS, enable outgoing encryption/MAC/compression.
local.host: Sending request for user-authentication service.
local.host: Service accepted: ssh-userauth.
local.host: Trying empty user-authentication request.
local.host: Authentication methods that can continue: publickey,password.
local.host: Next method to try is publickey.
local.host: Trying pubkey authentication with key file '/home/pp2/.ssh/id_dsa'
local.host: Authentication methods that can continue: publickey,password.
local.host: Next method to try is publickey.
local.host: Next method to try is password.
local.host: Trying password authentication.
local.host: Login completed, opening dummy shell channel.
local.host: channel 0: new [client-session]
local.host: Requesting channel_open for channel 0.
local.host: channel 0: open confirm rwindow 0 rmax 32768
local.host: Got channel open confirmation, requesting shell.
local.host: Requesting service shell on channel 0.
local.host: channel 1: new [client-session]
local.host: Requesting channel_open for channel 1.
local.host: Entering interactive session.
local.host: Sending command: passwd
local.host: Requesting service exec on channel 1.
local.host: channel 1: open confirm rwindow 0 rmax 32768
---------   <- MODO INTERACTIVO: old password
*********   <- MODO INTERACTIVO: new password
*********   <- MODO INTERACTIVO: repeat new password
local.host: input_channel_request: rtype exit-status reply 0
local.host: channel 1: rcvd eof
local.host: channel 1: output open -> drain
local.host: channel 1: rcvd close
local.host: channel 1: input open -> closed
local.host: channel 1: close_read
local.host: channel 1: obuf empty
local.host: channel 1: output drain -> closed
local.host: channel 1: close_write
local.host: channel 1: send close
local.host: channel 1: full closed

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