File Coverage

blib/lib/Net/SSH.pm
Criterion Covered Total %
statement 24 92 26.0
branch 0 34 0.0
condition 0 6 0.0
subroutine 8 15 53.3
pod 5 5 100.0
total 37 152 24.3


line stmt bran cond sub pod time code
1             package Net::SSH;
2              
3 1     1   802 use strict;
  1         2  
  1         37  
4 1     1   5 use vars qw($VERSION @ISA @EXPORT_OK $ssh $equalspace $DEBUG @ssh_options);
  1         1  
  1         93  
5 1     1   4 use Exporter;
  1         10  
  1         34  
6 1     1   846 use POSIX ":sys_wait_h";
  1         6269  
  1         5  
7 1     1   2129 use IO::File;
  1         10646  
  1         140  
8 1     1   926 use IO::Select;
  1         1745  
  1         47  
9 1     1   854 use IPC::Open2;
  1         4313  
  1         59  
10 1     1   7 use IPC::Open3;
  1         2  
  1         6979  
11              
12             @ISA = qw(Exporter);
13             @EXPORT_OK = qw( ssh issh ssh_cmd sshopen2 sshopen3 );
14             $VERSION = '0.09';
15              
16             $DEBUG = 0;
17              
18             $ssh = "ssh";
19              
20             =head1 NAME
21              
22             Net::SSH - Perl extension for secure shell
23              
24             =head1 SYNOPSIS
25              
26             use Net::SSH qw(ssh issh sshopen2 sshopen3);
27              
28             ssh('user@hostname', $command);
29              
30             issh('user@hostname', $command);
31              
32             ssh_cmd('user@hostname', $command);
33             ssh_cmd( {
34             user => 'user',
35             host => 'host.name',
36             command => 'command',
37             args => [ '-arg1', '-arg2' ],
38             stdin_string => "string\n",
39             } );
40              
41             sshopen2('user@hostname', $reader, $writer, $command);
42              
43             sshopen3('user@hostname', $writer, $reader, $error, $command);
44              
45             =head1 DESCRIPTION
46              
47             Simple wrappers around ssh commands.
48              
49             For an all-perl implementation that does not require the system B command,
50             see L instead.
51              
52             =head1 SUBROUTINES
53              
54             =over 4
55              
56             =item ssh [USER@]HOST, COMMAND [, ARGS ... ]
57              
58             Calls ssh in batch mode.
59              
60             =cut
61              
62             sub ssh {
63 0     0 1   my($host, @command) = @_;
64 0 0         @ssh_options = &_ssh_options unless @ssh_options;
65 0           my @cmd = ($ssh, @ssh_options, $host, @command);
66 0 0         warn "[Net::SSH::ssh] executing ". join(' ', @cmd). "\n"
67             if $DEBUG;
68 0           system(@cmd);
69             }
70              
71             =item issh [USER@]HOST, COMMAND [, ARGS ... ]
72              
73             Prints the ssh command to be executed, waits for the user to confirm, and
74             (optionally) executes the command.
75              
76             =cut
77              
78             sub issh {
79 0     0 1   my($host, @command) = @_;
80 0           my @cmd = ($ssh, $host, @command);
81 0           print join(' ', @cmd), "\n";
82 0 0         if ( &_yesno ) {
83 0           system(@cmd);
84             }
85             }
86              
87             =item ssh_cmd [USER@]HOST, COMMAND [, ARGS ... ]
88              
89             =item ssh_cmd OPTIONS_HASHREF
90              
91             Calls ssh in batch mode. Throws a fatal error if data occurs on the command's
92             STDERR. Returns any data from the command's STDOUT.
93              
94             If using the hashref-style of passing arguments, possible keys are:
95              
96             user (optional)
97             host (requried)
98             command (required)
99             args (optional, arrayref)
100             stdin_string (optional) - written to the command's STDIN
101              
102             =cut
103              
104             sub ssh_cmd {
105 0     0 1   my($host, $stdin_string, @command);
106 0 0         if ( ref($_[0]) ) {
107 0           my $opt = shift;
108 0           $host = $opt->{host};
109 0 0         $host = $opt->{user}. '@'. $host if exists $opt->{user};
110 0           @command = ( $opt->{command} );
111 0 0         push @command, @{ $opt->{args} } if exists $opt->{args};
  0            
112 0           $stdin_string = $opt->{stdin_string};
113             } else {
114 0           ($host, @command) = @_;
115 0           undef $stdin_string;
116             }
117              
118 0           my $reader = IO::File->new();
119 0           my $writer = IO::File->new();
120 0           my $error = IO::File->new();
121              
122 0 0         my $pid = sshopen3( $host, $writer, $reader, $error, @command ) or die $!;
123              
124 0 0         print $writer $stdin_string if defined $stdin_string;
125 0           close $writer;
126              
127 0           my $select = new IO::Select;
128 0           foreach ( $reader, $error ) { $select->add($_); }
  0            
129              
130 0           my($output_stream, $error_stream) = ('', '');
131 0           while ( $select->count ) {
132 0           my @handles = $select->can_read;
133 0           foreach my $handle ( @handles ) {
134 0           my $buffer = '';
135 0           my $bytes = sysread($handle, $buffer, 4096);
136 0 0         if ( !defined($bytes) ) {
137 0           waitpid($pid, WNOHANG);
138 0           die "[Net::SSH::ssh_cmd] $!"
139             };
140 0 0         $select->remove($handle) if !$bytes;
141 0 0         if ( $handle eq $reader ) {
    0          
142 0           $output_stream .= $buffer;
143             } elsif ( $handle eq $error ) {
144 0           $error_stream .= $buffer;
145             }
146             }
147              
148             }
149              
150 0           waitpid($pid, WNOHANG);
151              
152 0 0         die "$error_stream" if length($error_stream);
153              
154 0           return $output_stream;
155              
156             }
157              
158             =item sshopen2 [USER@]HOST, READER, WRITER, COMMAND [, ARGS ... ]
159              
160             Connects the supplied filehandles to the ssh process (in batch mode).
161              
162             =cut
163              
164             sub sshopen2 {
165 0     0 1   my($host, $reader, $writer, @command) = @_;
166 0 0         @ssh_options = &_ssh_options unless @ssh_options;
167 0           open2($reader, $writer, $ssh, @ssh_options, $host, @command);
168             }
169              
170             =item sshopen3 HOST, WRITER, READER, ERROR, COMMAND [, ARGS ... ]
171              
172             Connects the supplied filehandles to the ssh process (in batch mode).
173              
174             =cut
175              
176             sub sshopen3 {
177 0     0 1   my($host, $writer, $reader, $error, @command) = @_;
178 0 0         @ssh_options = &_ssh_options unless @ssh_options;
179 0           open3($writer, $reader, $error, $ssh, @ssh_options, $host, @command);
180             }
181              
182             sub _yesno {
183 0     0     print "Proceed [y/N]:";
184 0           my $x = scalar();
185 0           $x =~ /^y/i;
186             }
187              
188             sub _ssh_options {
189 0     0     my $reader = IO::File->new();
190 0           my $writer = IO::File->new();
191 0           my $error = IO::File->new();
192 0           open3($writer, $reader, $error, $ssh, '-V');
193 0           my $ssh_version = <$error>;
194 0           chomp($ssh_version);
195 0 0 0       if ( $ssh_version =~ /.*OpenSSH[-|_](\w+)\./ && $1 == 1 ) {
196 0           $equalspace = " ";
197             } else {
198 0           $equalspace = "=";
199             }
200 0           my @options = ( '-o', 'BatchMode'.$equalspace.'yes' );
201 0 0 0       if ( $ssh_version =~ /.*OpenSSH[-|_](\w+)\./ && $1 > 1 ) {
202 0           unshift @options, '-T';
203             }
204 0           @options;
205             }
206              
207             =back
208              
209             =head1 EXAMPLE
210              
211             use Net::SSH qw(sshopen2);
212             use strict;
213              
214             my $user = "username";
215             my $host = "hostname";
216             my $cmd = "command";
217              
218             sshopen2("$user\@$host", *READER, *WRITER, "$cmd") || die "ssh: $!";
219              
220             while () {
221             chomp();
222             print "$_\n";
223             }
224              
225             close(READER);
226             close(WRITER);
227              
228             =head1 FREQUENTLY ASKED QUESTIONS
229              
230             Q: How do you supply a password to connect with ssh within a perl script
231             using the Net::SSH module?
232              
233             A: You don't (at least not with this module). Use RSA or DSA keys. See the
234             quick help in the next section and the ssh-keygen(1) manpage.
235              
236             A #2: See L instead.
237              
238             Q: My script is "leaking" ssh processes.
239              
240             A: See L, L,
241             L and L.
242              
243             =head1 GENERATING AND USING SSH KEYS
244              
245             =over 4
246              
247             =item 1 Generate keys
248              
249             Type:
250              
251             ssh-keygen -t rsa
252              
253             And do not enter a passphrase unless you wanted to be prompted for
254             one during file copying.
255              
256             Here is what you will see:
257              
258             $ ssh-keygen -t rsa
259             Generating public/private rsa key pair.
260             Enter file in which to save the key (/home/User/.ssh/id_rsa):
261             Enter passphrase (empty for no passphrase):
262              
263             Enter same passphrase again:
264              
265             Your identification has been saved in /home/User/.ssh/id_rsa.
266             Your public key has been saved in /home/User/.ssh/id_rsa.pub.
267             The key fingerprint is:
268             5a:cd:2b:0a:cd:d9:15:85:26:79:40:0c:55:2a:f4:23 User@JEFF-CPU
269              
270              
271             =item 2 Copy public to machines you want to upload to
272              
273             C is your public key. Copy it to C<~/.ssh> on target machine.
274              
275             Put a copy of the public key file on each machine you want to log into.
276             Name the copy C (some implementations name this file
277             C)
278              
279             Then type:
280              
281             chmod 600 authorized_keys
282              
283             Then make sure your home dir on the remote machine is not group or
284             world writeable.
285              
286             =back
287              
288             =head1 AUTHORS
289              
290             Ivan Kohler
291              
292             Assistance wanted - this module could really use a maintainer with enough time
293             to at least review and apply more patches. Or the module should just be
294             deprecated in favor of Net::SSH::Expect or made into an ::Any style
295             compatibility wrapper that uses whatver implementation is avaialble
296             (Net::SSH2, Net::SSH::Perl or shelling out like the module does now). Please
297             email Ivan if you are interested in helping.
298              
299             John Harrison contributed an example for the documentation.
300              
301             Martin Langhoff contributed the ssh_cmd command, and
302             Jeff Finucane updated it and took care of the 0.04 release.
303              
304             Anthony Awtrey contributed a fix for those still using
305             OpenSSH v1.
306              
307             Thanks to terrence brannon for the documentation in
308             the GENERATING AND USING SSH KEYS section.
309              
310             =head1 COPYRIGHT
311              
312             Copyright (c) 2004 Ivan Kohler.
313             Copyright (c) 2007-2008 Freeside Internet Services, Inc.
314             All rights reserved.
315             This program is free software; you can redistribute it and/or modify it under
316             the same terms as Perl itself.
317              
318             =head1 BUGS
319              
320             Not OO.
321              
322             Look at IPC::Session (also fsh, well now the native SSH "master mode" stuff)
323              
324             =head1 SEE ALSO
325              
326             For a perl implementation that does not require the system B command, see
327             L instead.
328              
329             For a wrapper version that allows you to use passwords, see L
330             instead.
331              
332             For another non-forking version that uses the libssh2 library, see
333             L.
334              
335             For a way to execute remote Perl code over an ssh connection see
336             L.
337              
338             ssh-keygen(1), ssh(1), L, L, L
339              
340             =cut
341              
342             1;
343