| Filename | /2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/Net/SSH.pm |
| Statements | Executed 30 statements in 1.12ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 1.53ms | 1.77ms | Net::SSH::BEGIN@9 |
| 1 | 1 | 1 | 949µs | 1.11ms | Net::SSH::BEGIN@8 |
| 1 | 1 | 1 | 601µs | 4.84ms | Net::SSH::BEGIN@7 |
| 1 | 1 | 1 | 16µs | 20µs | Net::SSH::BEGIN@3 |
| 1 | 1 | 1 | 9µs | 179µs | Net::SSH::BEGIN@6 |
| 1 | 1 | 1 | 9µs | 26µs | Net::SSH::BEGIN@10 |
| 1 | 1 | 1 | 9µs | 95µs | Net::SSH::BEGIN@4 |
| 1 | 1 | 1 | 9µs | 22µs | Net::SSH::BEGIN@5 |
| 0 | 0 | 0 | 0s | 0s | Net::SSH::_ssh_options |
| 0 | 0 | 0 | 0s | 0s | Net::SSH::_yesno |
| 0 | 0 | 0 | 0s | 0s | Net::SSH::issh |
| 0 | 0 | 0 | 0s | 0s | Net::SSH::ssh |
| 0 | 0 | 0 | 0s | 0s | Net::SSH::ssh_cmd |
| 0 | 0 | 0 | 0s | 0s | Net::SSH::sshopen2 |
| 0 | 0 | 0 | 0s | 0s | Net::SSH::sshopen3 |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package Net::SSH; | ||||
| 2 | |||||
| 3 | 3 | 27µs | 2 | 25µs | # spent 20µs (16+5) within Net::SSH::BEGIN@3 which was called:
# once (16µs+5µs) by Tapper::MCP::Net::BEGIN@11 at line 3 # spent 20µs making 1 call to Net::SSH::BEGIN@3
# spent 5µs making 1 call to strict::import |
| 4 | 3 | 22µs | 2 | 181µs | # spent 95µs (9+86) within Net::SSH::BEGIN@4 which was called:
# once (9µs+86µs) by Tapper::MCP::Net::BEGIN@11 at line 4 # spent 95µs making 1 call to Net::SSH::BEGIN@4
# spent 86µs making 1 call to vars::import |
| 5 | 3 | 20µs | 2 | 36µs | # spent 22µs (9+14) within Net::SSH::BEGIN@5 which was called:
# once (9µs+14µs) by Tapper::MCP::Net::BEGIN@11 at line 5 # spent 22µs making 1 call to Net::SSH::BEGIN@5
# spent 14µs making 1 call to Exporter::import |
| 6 | 3 | 22µs | 2 | 348µs | # spent 179µs (9+170) within Net::SSH::BEGIN@6 which was called:
# once (9µs+170µs) by Tapper::MCP::Net::BEGIN@11 at line 6 # spent 179µs making 1 call to Net::SSH::BEGIN@6
# spent 170µs making 1 call to POSIX::import |
| 7 | 3 | 129µs | 2 | 4.97ms | # spent 4.84ms (601µs+4.24) within Net::SSH::BEGIN@7 which was called:
# once (601µs+4.24ms) by Tapper::MCP::Net::BEGIN@11 at line 7 # spent 4.84ms making 1 call to Net::SSH::BEGIN@7
# spent 129µs making 1 call to Exporter::import |
| 8 | 3 | 112µs | 2 | 1.14ms | # spent 1.11ms (949µs+165µs) within Net::SSH::BEGIN@8 which was called:
# once (949µs+165µs) by Tapper::MCP::Net::BEGIN@11 at line 8 # spent 1.11ms making 1 call to Net::SSH::BEGIN@8
# spent 24µs making 1 call to Exporter::import |
| 9 | 3 | 99µs | 2 | 1.80ms | # spent 1.77ms (1.53+236µs) within Net::SSH::BEGIN@9 which was called:
# once (1.53ms+236µs) by Tapper::MCP::Net::BEGIN@11 at line 9 # spent 1.77ms making 1 call to Net::SSH::BEGIN@9
# spent 25µs making 1 call to Exporter::import |
| 10 | 3 | 680µs | 2 | 43µs | # spent 26µs (9+17) within Net::SSH::BEGIN@10 which was called:
# once (9µs+17µs) by Tapper::MCP::Net::BEGIN@11 at line 10 # spent 26µs making 1 call to Net::SSH::BEGIN@10
# spent 17µs making 1 call to Exporter::import |
| 11 | |||||
| 12 | 1 | 7µs | @ISA = qw(Exporter); | ||
| 13 | 1 | 1µs | @EXPORT_OK = qw( ssh issh ssh_cmd sshopen2 sshopen3 ); | ||
| 14 | 1 | 400ns | $VERSION = '0.09'; | ||
| 15 | |||||
| 16 | 1 | 300ns | $DEBUG = 0; | ||
| 17 | |||||
| 18 | 1 | 300ns | $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<ssh> command, | ||||
| 50 | see L<Net::SSH::Perl> 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 | my($host, @command) = @_; | ||||
| 64 | @ssh_options = &_ssh_options unless @ssh_options; | ||||
| 65 | my @cmd = ($ssh, @ssh_options, $host, @command); | ||||
| 66 | warn "[Net::SSH::ssh] executing ". join(' ', @cmd). "\n" | ||||
| 67 | if $DEBUG; | ||||
| 68 | 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 | my($host, @command) = @_; | ||||
| 80 | my @cmd = ($ssh, $host, @command); | ||||
| 81 | print join(' ', @cmd), "\n"; | ||||
| 82 | if ( &_yesno ) { | ||||
| 83 | 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 | my($host, $stdin_string, @command); | ||||
| 106 | if ( ref($_[0]) ) { | ||||
| 107 | my $opt = shift; | ||||
| 108 | $host = $opt->{host}; | ||||
| 109 | $host = $opt->{user}. '@'. $host if exists $opt->{user}; | ||||
| 110 | @command = ( $opt->{command} ); | ||||
| 111 | push @command, @{ $opt->{args} } if exists $opt->{args}; | ||||
| 112 | $stdin_string = $opt->{stdin_string}; | ||||
| 113 | } else { | ||||
| 114 | ($host, @command) = @_; | ||||
| 115 | undef $stdin_string; | ||||
| 116 | } | ||||
| 117 | |||||
| 118 | my $reader = IO::File->new(); | ||||
| 119 | my $writer = IO::File->new(); | ||||
| 120 | my $error = IO::File->new(); | ||||
| 121 | |||||
| 122 | my $pid = sshopen3( $host, $writer, $reader, $error, @command ) or die $!; | ||||
| 123 | |||||
| 124 | print $writer $stdin_string if defined $stdin_string; | ||||
| 125 | close $writer; | ||||
| 126 | |||||
| 127 | my $select = new IO::Select; | ||||
| 128 | foreach ( $reader, $error ) { $select->add($_); } | ||||
| 129 | |||||
| 130 | my($output_stream, $error_stream) = ('', ''); | ||||
| 131 | while ( $select->count ) { | ||||
| 132 | my @handles = $select->can_read; | ||||
| 133 | foreach my $handle ( @handles ) { | ||||
| 134 | my $buffer = ''; | ||||
| 135 | my $bytes = sysread($handle, $buffer, 4096); | ||||
| 136 | if ( !defined($bytes) ) { | ||||
| 137 | waitpid($pid, WNOHANG); | ||||
| 138 | die "[Net::SSH::ssh_cmd] $!" | ||||
| 139 | }; | ||||
| 140 | $select->remove($handle) if !$bytes; | ||||
| 141 | if ( $handle eq $reader ) { | ||||
| 142 | $output_stream .= $buffer; | ||||
| 143 | } elsif ( $handle eq $error ) { | ||||
| 144 | $error_stream .= $buffer; | ||||
| 145 | } | ||||
| 146 | } | ||||
| 147 | |||||
| 148 | } | ||||
| 149 | |||||
| 150 | waitpid($pid, WNOHANG); | ||||
| 151 | |||||
| 152 | die "$error_stream" if length($error_stream); | ||||
| 153 | |||||
| 154 | 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 | my($host, $reader, $writer, @command) = @_; | ||||
| 166 | @ssh_options = &_ssh_options unless @ssh_options; | ||||
| 167 | 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 | my($host, $writer, $reader, $error, @command) = @_; | ||||
| 178 | @ssh_options = &_ssh_options unless @ssh_options; | ||||
| 179 | open3($writer, $reader, $error, $ssh, @ssh_options, $host, @command); | ||||
| 180 | } | ||||
| 181 | |||||
| 182 | sub _yesno { | ||||
| 183 | print "Proceed [y/N]:"; | ||||
| 184 | my $x = scalar(<STDIN>); | ||||
| 185 | $x =~ /^y/i; | ||||
| 186 | } | ||||
| 187 | |||||
| 188 | sub _ssh_options { | ||||
| 189 | my $reader = IO::File->new(); | ||||
| 190 | my $writer = IO::File->new(); | ||||
| 191 | my $error = IO::File->new(); | ||||
| 192 | open3($writer, $reader, $error, $ssh, '-V'); | ||||
| 193 | my $ssh_version = <$error>; | ||||
| 194 | chomp($ssh_version); | ||||
| 195 | if ( $ssh_version =~ /.*OpenSSH[-|_](\w+)\./ && $1 == 1 ) { | ||||
| 196 | $equalspace = " "; | ||||
| 197 | } else { | ||||
| 198 | $equalspace = "="; | ||||
| 199 | } | ||||
| 200 | my @options = ( '-o', 'BatchMode'.$equalspace.'yes' ); | ||||
| 201 | if ( $ssh_version =~ /.*OpenSSH[-|_](\w+)\./ && $1 > 1 ) { | ||||
| 202 | unshift @options, '-T'; | ||||
| 203 | } | ||||
| 204 | @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 (<READER>) { | ||||
| 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<Net::SSH::Expect> instead. | ||||
| 237 | |||||
| 238 | Q: My script is "leaking" ssh processes. | ||||
| 239 | |||||
| 240 | A: See L<perlfaq8/"How do I avoid zombies on a Unix system">, L<IPC::Open2>, | ||||
| 241 | L<IPC::Open3> and L<perlfunc/waitpid>. | ||||
| 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<id_rsa.pub> 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<authorized_keys> (some implementations name this file | ||||
| 277 | C<authorized_keys2>) | ||||
| 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 <ivan-netssh_pod@420.am> | ||||
| 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 <japh@in-ta.net> contributed an example for the documentation. | ||||
| 300 | |||||
| 301 | Martin Langhoff <martin@cwa.co.nz> contributed the ssh_cmd command, and | ||||
| 302 | Jeff Finucane <jeff@cmh.net> updated it and took care of the 0.04 release. | ||||
| 303 | |||||
| 304 | Anthony Awtrey <tony@awtrey.com> contributed a fix for those still using | ||||
| 305 | OpenSSH v1. | ||||
| 306 | |||||
| 307 | Thanks to terrence brannon <tbone@directsynergy.com> 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<ssh> command, see | ||||
| 327 | L<Net::SSH::Perl> instead. | ||||
| 328 | |||||
| 329 | For a wrapper version that allows you to use passwords, see L<Net::SSH::Expect> | ||||
| 330 | instead. | ||||
| 331 | |||||
| 332 | For another non-forking version that uses the libssh2 library, see | ||||
| 333 | L<Net::SSH2>. | ||||
| 334 | |||||
| 335 | For a way to execute remote Perl code over an ssh connection see | ||||
| 336 | L<IPC::PerlSSH>. | ||||
| 337 | |||||
| 338 | ssh-keygen(1), ssh(1), L<IO::File>, L<IPC::Open2>, L<IPC::Open3> | ||||
| 339 | |||||
| 340 | =cut | ||||
| 341 | |||||
| 342 | 1 | 5µs | 1; | ||
| 343 |