File Coverage

blib/lib/IPC/PerlSSH.pm
Criterion Covered Total %
statement 96 114 84.2
branch 25 48 52.0
condition 4 6 66.6
subroutine 19 19 100.0
pod 6 8 75.0
total 150 195 76.9


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2006-2012,2016 -- leonerd@leonerd.org.uk
5              
6             package IPC::PerlSSH;
7              
8 12     12   262788 use strict;
  12         22  
  12         359  
9 12     12   48 use warnings;
  12         16  
  12         353  
10              
11 12     12   47 use base qw( IPC::PerlSSH::Base );
  12         18  
  12         5175  
12              
13 12     12   5495 use IPC::Open2;
  12         46774  
  12         671  
14              
15 12     12   153 use Carp;
  12         17  
  12         11582  
16              
17             our $VERSION = '0.17';
18              
19             our $READLEN = 256*1024; # 256KiB
20              
21             =head1 NAME
22              
23             C - execute remote perl code over an SSH link
24              
25             =head1 SYNOPSIS
26              
27             use IPC::PerlSSH;
28              
29             my $ips = IPC::PerlSSH->new( Host => "over.there" );
30              
31             $ips->eval( "use POSIX qw( uname )" );
32             my @remote_uname = $ips->eval( "uname()" );
33              
34             # We can pass arguments
35             $ips->eval( 'open FILE, ">", $_[0]; print FILE $_[1]; close FILE;',
36             "foo.txt", "Hello, world!" );
37              
38             # We can pre-compile stored procedures
39             $ips->store( "get_file", 'local $/;
40             open FILE, "<", $_[0];
41             $_ = ;
42             close FILE;
43             return $_;' );
44             foreach my $file ( @files ) {
45             my $content = $ips->call( "get_file", $file );
46             ...
47             }
48              
49             # We can use existing libraries for remote stored procedures
50             $ips->use_library( "FS", qw( readfile ) );
51             foreach my $file ( @files ) {
52             my $content = $ips->call( "readfile", $file );
53             ...
54             }
55              
56             =head1 DESCRIPTION
57              
58             This module provides an object class that provides a mechanism to execute perl
59             code in a remote instance of perl running on another host, communicated via an
60             SSH link or similar connection. Where it differs from most other IPC modules
61             is that no special software is required on the remote end, other than the
62             ability to run perl. In particular, it is not required that the
63             C module is installed there. Nor are any special administrative
64             rights required; any account that has shell access and can execute the perl
65             binary on the remote host can use this module.
66              
67             =head2 Argument Passing
68              
69             The arguments to, and return values from, remote code are always transferred
70             as lists of strings. This has the following effects on various types of
71             values:
72              
73             =over 8
74              
75             =item *
76              
77             String values are passed as they stand.
78              
79             =item *
80              
81             Booleans and integers will become stringified, but will work as expected once
82             they reach the other side of the connection.
83              
84             =item *
85              
86             Floating-point numbers will get converted to a decimal notation, which may
87             lose precision.
88              
89             =item *
90              
91             A single array of strings, or a single hash of string values, can be passed
92             by-value as a list, possibly after positional arguments:
93              
94             $ips->store( 'foo', 'my ( $arg, @list ) = @_; ...' );
95              
96             $ips->store( 'bar', 'my %opts = @_; ...' );
97              
98             =item *
99              
100             No reference value, including IO handles, can be passed; instead it will be
101             stringified.
102              
103             =back
104              
105             To pass or return a more complex structure, consider using a module such as
106             L, which can serialise the structure into a plain string, to be
107             deserialised on the remote end. Be aware however, that C was only
108             added to core in perl 5.7.3, so if the remote perl is older, it may not be
109             available.
110              
111             To work with remote IO handles, see the L module.
112              
113             =cut
114              
115             =head1 CONSTRUCTORS
116              
117             =cut
118              
119             =head2 new (with Host)
120              
121             $ips = IPC::PerlSSH->new( Host => $host, ... )
122              
123             Returns a new instance of a C object connected to the specified
124             host. The following arguments can be specified:
125              
126             =over 8
127              
128             =item Host => STRING
129              
130             Connect to a named host.
131              
132             =item Port => INT
133              
134             Optionally specify a non-default port.
135              
136             =item Perl => STRING
137              
138             Optionally pass in the path to the perl binary in the remote host.
139              
140             =item User => STRING
141              
142             Optionally pass in an alternative username
143              
144             =item SshPath => STRING
145              
146             Optionally specify a different path to the F binary
147              
148             =item SshOptions => ARRAY
149              
150             Optionally specify any other options to pass to the F binary, in an
151             C reference
152              
153             =back
154              
155             =head2 new (with Command)
156              
157             $ips = IPC::PerlSSH->new( Command => \@command, ... )
158              
159             Returns a new instance of a C object which uses the STDIN/STDOUT
160             streams of a command it executes, as the streams to communicate with the
161             remote F.
162              
163             =over 8
164              
165             =item Command => ARRAY
166              
167             Specifies the command to execute
168              
169             =item Command => STRING
170              
171             Shorthand form for executing a single simple path
172              
173             =back
174              
175             The C key can be used to create an C running perl
176             directly on the local machine, for example; so that the "remote" perl is in
177             fact running locally, but still in its own process.
178              
179             my $ips = IPC::PerlSSH->new( Command => $^X );
180              
181             =head2 new (with Readh + Writeh)
182              
183             $ips = IPC::PerlSSH->new( Readh => $rd, Writeh => $wr )
184              
185             Returns a new instance of a C object using a given pair of
186             filehandles to read from and write to the remote F process. It is
187             allowable for both filehandles to be the same - for example using a socket.
188              
189             =head2 new (with Readfunc + Writefunc)
190              
191             $ips = IPC::PerlSSH->new( Readfunc => \&read, Writefunc => \&write )
192              
193             Returns a new instance of a C object using a given pair of
194             functions as read and write operators.
195              
196             Usually this form won't be used in practice; it largely exists to assist the
197             test scripts. But since it works, it is included in the interface in case the
198             earlier alternatives are not suitable.
199              
200             The functions are called as
201              
202             $len = $Readfunc->( my $buffer, $maxlen );
203              
204             $len = $Writewrite->( $buffer );
205              
206             In each case, the returned value should be the number of bytes read or
207             written.
208              
209             =cut
210              
211             sub new
212             {
213 12     12 1 2886 my $class = shift;
214 12         45 my %opts = @_;
215              
216 12         59 my $self = bless {
217             readbuff => "",
218             stored => {},
219             }, $class;
220              
221 12         37 my ( $readfunc, $writefunc ) = ( delete $opts{Readfunc}, delete $opts{Writefunc} );
222              
223 12         21 my $pid = delete $opts{Pid};
224              
225 12 100 66     77 if( !defined $readfunc || !defined $writefunc ) {
226 11         26 my ( $readh, $writeh ) = ( delete $opts{Readh}, delete $opts{Writeh} );
227              
228 11 100 66     42 if( !defined $readh || !defined $writeh ) {
229 10         94 my @command = $self->build_command_from( \%opts );
230 10         53 $pid = open2( $readh, $writeh, @command );
231             }
232              
233             $readfunc = sub {
234 73     73   97088 sysread( $readh, $_[0], $_[1] );
235 11         25633 };
236              
237             $writefunc = sub {
238 83     83   2544 syswrite( $writeh, $_[0] );
239 11         62 };
240             }
241              
242 12 50       93 keys %opts and
243             croak "Unexpected ->new keys - " . join ", ", sort keys %opts;
244              
245 12         155 $self->{pid} = $pid;
246 12         35 $self->{readfunc} = $readfunc;
247 12         279 $self->{writefunc} = $writefunc;
248              
249 12         133 $self->send_firmware;
250              
251 12         76 return $self;
252             }
253              
254             sub write
255             {
256 89     89 0 112 my $self = shift;
257 89         111 my ( $data ) = @_;
258              
259 89         222 $self->{writefunc}->( $data );
260             }
261              
262             sub read_message
263             {
264 77     77 0 102 my $self = shift;
265              
266 77         81 my ( $message, @args );
267              
268 77         173 while( !defined $message ) {
269 78         68 my $b;
270 78 100       184 $self->{readfunc}->( $b, $READLEN ) or return ( "CLOSED" );
271 77         367 $self->{readbuff} .= $b;
272 77         399 ( $message, @args ) = $self->parse_message( $self->{readbuff} );
273             }
274              
275 76         1988 return ( $message, @args );
276             }
277              
278             =head1 METHODS
279              
280             =cut
281              
282             =head2 eval
283              
284             @result = $ips->eval( $code, @args )
285              
286             This method evaluates code in the remote host, passing arguments and returning
287             the result.
288              
289             The code should be passed in a string, and is evaluated using a string
290             C in the remote host, in list context. If this method is called in
291             scalar context, then only the first element of the returned list is returned.
292              
293             If the remote code threw an exception, then this function propagates it as a
294             plain string. If the remote process exits before responding, this will be
295             propagated as an exception.
296              
297             =cut
298              
299             sub eval
300             {
301 18     18 1 15951 my $self = shift;
302 18         534 my ( $code, @args ) = @_;
303              
304 18         188 $self->write_message( "EVAL", $code, @args );
305              
306 18         80 my ( $ret, @retargs ) = $self->read_message;
307              
308 18 100       249 if( $ret eq "RETURNED" ) {
    50          
    50          
309             # If the caller didn't want an array and we received more than one result
310             # from the far end; we'll just have to throw it away...
311 17 100       2174 return wantarray ? @retargs : $retargs[0];
312             }
313             elsif( $ret eq "DIED" ) {
314 0         0 my ( $message ) = @retargs;
315 0 0       0 if( $message =~ m/^While compiling code:.* at \(eval \d+\) line (\d+)/ ) {
316 0         0 $message .= " ==> " . (split m/\n/, $code)[$1 - 1] . "\n";
317             }
318 0         0 die "Remote host threw an exception:\n$message";
319             }
320             elsif( $ret eq "CLOSED" ) {
321 1         18 die "Remote connection closed\n";
322             }
323             else {
324 0         0 die "Unknown return result $ret\n";
325             }
326             }
327              
328             =head2 store
329              
330             $ips->store( $name, $code )
331              
332             $ips->store( %funcs )
333              
334             This method sends code to the remote host to store in named procedure(s) which
335             can be executed later. The code should be passed in strings.
336              
337             While the code is not executed, it will still be compiled into CODE references
338             in the remote host. Any compile errors that occur will be throw as exceptions
339             by this method.
340              
341             Multiple functions may be passed in a hash, to reduce the number of network
342             roundtrips, which may help latency.
343              
344             =cut
345              
346             sub store
347             {
348 7     7 1 2995 my $self = shift;
349 7         26 my %funcs = @_;
350              
351 7         22 foreach my $name ( keys %funcs ) {
352 7 100       22 $self->_has_stored_code( $name ) and croak "Already have a stored function called '$name'";
353             }
354              
355 5         22 $self->write_message( "STORE", %funcs );
356              
357 5         18 my ( $ret, @retargs ) = $self->read_message;
358              
359 5 50       22 if( $ret eq "OK" ) {
    0          
    0          
360 5         30 $self->{stored}{$_} = 1 for keys %funcs;
361 5         16 return;
362             }
363             elsif( $ret eq "DIED" ) {
364 0         0 my ( $message ) = @retargs;
365 0 0       0 if( $message =~ m/^While compiling code for (\S+):.* at \(eval \d+\) line (\d+)/ ) {
366 0         0 my $code = $funcs{$1};
367 0         0 $message .= " ==> " . (split m/\n/, $code)[$2 - 1] . "\n";
368             }
369 0         0 die "Remote host threw an exception:\n$message";
370             }
371             elsif( $ret eq "CLOSED" ) {
372 0         0 die "Remote connection closed\n";
373             }
374             else {
375 0         0 die "Unknown return result $ret\n";
376             }
377             }
378              
379             sub _has_stored_code
380             {
381 131     131   159 my $self = shift;
382 131         121 my ( $name ) = @_;
383 131         838 return exists $self->{stored}{$name};
384             }
385              
386             =head2 bind
387              
388             $ips->bind( $name, $code )
389              
390             This method is identical to the C method, except that the remote
391             function will be available as a plain function within the local perl
392             program, as a function of the given name in the caller's package.
393              
394             =cut
395              
396             sub bind
397             {
398 2     2 1 863 my $self = shift;
399 2         5 my ( $name, $code ) = @_;
400              
401 2         6 $self->store( $name, $code );
402              
403 2         8 my $caller = (caller)[0];
404             {
405 12     12   77 no strict 'refs';
  12         23  
  12         5264  
  2         5  
406 2     2   15 *{$caller."::$name"} = sub { $self->call( $name, @_ ) };
  2         20  
  2         12  
407             }
408             }
409              
410             =head2 call
411              
412             @result = $ips->call( $name, @args )
413              
414             This method invokes a remote method that has earlier been defined using the
415             C or C methods. The arguments are passed and the result is
416             returned in the same way as with the C method.
417              
418             If an exception occurs during execution, it is propagated and thrown by this
419             method. If the remote process exits before responding, this will be propagated
420             as an exception.
421              
422             =cut
423              
424             sub call
425             {
426 48     48 1 69936 my $self = shift;
427 48         136 my ( $name, @args ) = @_;
428              
429 48 50       118 $self->_has_stored_code( $name ) or croak "Do not have a stored function called '$name'";
430              
431 48         175 $self->write_message( "CALL", $name, @args );
432              
433 48         118 my ( $ret, @retargs ) = $self->read_message;
434              
435 48 50       109 if( $ret eq "RETURNED" ) {
    0          
    0          
436             # If the caller didn't want an array and we received more than one result
437             # from the far end; we'll just have to throw it away...
438 48 100       216 return wantarray ? @retargs : $retargs[0];
439             }
440             elsif( $ret eq "DIED" ) {
441 0         0 die "Remote host threw an exception:\n$retargs[0]";
442             }
443             elsif( $ret eq "CLOSED" ) {
444 0         0 die "Remote connection closed\n";
445             }
446             else {
447 0         0 die "Unknown return result $ret\n";
448             }
449             }
450              
451             =head2 use_library
452              
453             $ips->use_library( $library, @funcs )
454              
455             This method loads a library of code from a module, and stores them to the
456             remote perl by calling C on each one. The C<$library> name may be a
457             full class name, or a name within the C space.
458              
459             If the C<@funcs> list is non-empty, then only those named functions are stored
460             (analogous to the C perl statement). This may be useful in large
461             libraries that define many functions, only a few of which are actually used.
462              
463             For more information, see L.
464              
465             =cut
466              
467             sub use_library
468             {
469 9     9 1 1913 my $self = shift;
470              
471 9         51 my ( $package, $funcs ) = $self->load_library_pkg( @_ );
472              
473 6 100       27 $self->{stored_pkg}{$package} and delete $funcs->{_init};
474              
475 6         72 $self->write_message( "STOREPKG", $package, %$funcs );
476              
477 6         24 my ( $ret, @retargs ) = $self->read_message;
478              
479 6 50       50 if( $ret eq "OK" ) {
    0          
    0          
480 6         18 $self->{stored_pkg}{$package} = 1;
481 6         80 $self->{stored}{$_} = 1 for keys %$funcs;
482 6         33 return;
483             }
484             elsif( $ret eq "DIED" ) {
485 0         0 die "Remote host threw an exception:\n$retargs[0]";
486             }
487             elsif( $ret eq "CLOSED" ) {
488 0         0 die "Remote connection closed\n";
489             }
490             else {
491 0         0 die "Unknown return result $ret\n";
492             }
493             }
494              
495             sub DESTROY
496             {
497 10     10   6967 my $self = shift;
498              
499 10         161 undef $self->{readfunc};
500 10         967 undef $self->{writefunc};
501             # This will clean up the closures, and hence close the filehandles that are
502             # referenced by them. The remote perl will then shut down, and we can wait
503             # for the child process to exit
504              
505 10 100       3840 waitpid $self->{pid}, 0 if defined $self->{pid};
506             }
507              
508             =head1 AUTHOR
509              
510             Paul Evans
511              
512             =cut
513              
514             0x55AA;