Thread: [Ssh-sftp-perl-users] quick question with regard to exec, take 2
Brought to you by:
dbrobins
From: Jeremy K. <ki...@sc...> - 2009-04-02 18:05:57
Attachments:
signature.asc
|
I'm trying to write a quick program which will execute a series of commands on the remote system and get each individual exit status back from the commands. It appears the way to go about doing this is to create a new channel, exec, get the exit status, destroy the channel, exec, get the exit status, etc. However, I *also* want to grab the output of these commands (stdout and stderr) in real time, so I'm trying to use poll. Now, I could be going about this completely the wrong way. If I am, please let me know :) $channel->shell doesn't seem like it fits for me as I don't think I can get the exit statuses back from the remote commands being run. Here's a bit of what I have so far (which isn't working): my $channel = $ssh->channel; $channel->exec("sleep 5 && echo 'moo' && sleep 1"); print "\n"; while (1) { print "loop\n"; my @poll = ({handle => $channel, events => ['in','err']}); if ($ssh->poll(500, \@poll)) { # handle events } print Dumper($poll[0]->{revents}); } everything is all well and good until the command finishes (after the sleep 5), when polling completely blocks. Nothing further ever happens. If I kill the remote sshd process handling the connection (the user@notty process) then it returns these events: $VAR1 = { 'in' => 1, 'value' => 129, 'listener_closed' => 1, 'channel_closed' => 1 }; Is there some step I'm missing to make this work how I want? -Jeremy |
From: Thierry C. <thi...@gm...> - 2009-04-03 21:06:18
|
Jeremy Kitchen a écrit : > I'm trying to write a quick program which will execute a series of > commands on the remote system and get each individual exit status back > from the commands. > > It appears the way to go about doing this is to create a new channel, > exec, get the exit status, destroy the channel, exec, get the exit > status, etc. > > However, I *also* want to grab the output of these commands (stdout and > stderr) in real time, so I'm trying to use poll. > > Now, I could be going about this completely the wrong way. If I am, > please let me know :) > > I don't know if you are going the wrong way. However, I don't understand why you are not using ( $out, $err, $exit ) = $ssh->cmd( "$cmd" ); ? You can even execute a complete script shell using sthis syntax: ( $out, $err, $exit ) = $ssh->cmd( "bash", "$myscrypt" ); Isn't it simpler ? |
From: Jeremy K. <ki...@sc...> - 2009-04-03 21:58:08
Attachments:
signature.asc
|
Thierry CHICH wrote: > Jeremy Kitchen a écrit : >> I'm trying to write a quick program which will execute a series of >> commands on the remote system and get each individual exit status back >> from the commands. >> >> It appears the way to go about doing this is to create a new channel, >> exec, get the exit status, destroy the channel, exec, get the exit >> status, etc. >> >> However, I *also* want to grab the output of these commands (stdout and >> stderr) in real time, so I'm trying to use poll. >> >> Now, I could be going about this completely the wrong way. If I am, >> please let me know :) >> >> > I don't know if you are going the wrong way. However, I don't > understand why you are not using > ( $out, $err, $exit ) = $ssh->cmd( "$cmd" ); ? > > You can even execute a complete script shell using sthis syntax: > > ( $out, $err, $exit ) = $ssh->cmd( "bash", "$myscrypt" ); > Isn't it simpler ? > I'm not using Net::SSH::Perl, I'm using Net::SSH2. Net::SSH::Perl can't connect to several of our machines, but Net::SSH2 can. Also, using Net::SSH2's ->cmd method still doesn't give me 'real time' reading of the outputs. I *do* want to do something like what ->cmd does eventually, for really stupid easy stuff where we don't really care about the output until it's done (or commands that are *really* quick) but in the mean time I'm trying to get the realtime stuff working. -Jeremy |
From: Thierry C. <thi...@gm...> - 2009-04-04 21:27:58
|
Jeremy Kitchen a écrit : > Thierry CHICH wrote: > >> Jeremy Kitchen a écrit : >> >>> I'm trying to write a quick program which will execute a series of >>> commands on the remote system and get each individual exit status back >>> from the commands. >>> >>> It appears the way to go about doing this is to create a new channel, >>> exec, get the exit status, destroy the channel, exec, get the exit >>> status, etc. >>> >>> However, I *also* want to grab the output of these commands (stdout and >>> stderr) in real time, so I'm trying to use poll. >>> >>> Now, I could be going about this completely the wrong way. If I am, >>> please let me know :) >>> >>> >>> >> I don't know if you are going the wrong way. However, I don't >> understand why you are not using >> ( $out, $err, $exit ) = $ssh->cmd( "$cmd" ); ? >> >> You can even execute a complete script shell using sthis syntax: >> >> ( $out, $err, $exit ) = $ssh->cmd( "bash", "$myscrypt" ); >> Isn't it simpler ? >> >> > > I'm not using Net::SSH::Perl, I'm using Net::SSH2. Net::SSH::Perl can't > connect to several of our machines, but Net::SSH2 can. Also, using > Net::SSH2's ->cmd method still doesn't give me 'real time' reading of > the outputs. I *do* want to do something like what ->cmd does > eventually, for really stupid easy stuff where we don't really care > about the output until it's done (or commands that are *really* quick) > but in the mean time I'm trying to get the realtime stuff working. > > -Jeremy > Ok. I should have seen that the syntax was not coming form the Net::SSH::Perl I have not use Net::SSH2 as you have : for me, there is a big lack to the libssh2 library, and it is the lack of ssh-agent support. So it could be a stupid suggestion, but have you try to put $channel->blocking(0); at the beginning of your script ? I remember I had problem without this line. > ------------------------------------------------------------------------ > > ------------------------------------------------------------------------------ > > ------------------------------------------------------------------------ > > _______________________________________________ > Ssh-sftp-perl-users mailing list > Ssh...@li... > https://lists.sourceforge.net/lists/listinfo/ssh-sftp-perl-users > |
From: Jeremy K. <ki...@sc...> - 2009-04-03 21:56:19
Attachments:
signature.asc
|
Stefan Adling wrote: > my $ssh = Net::SSH::Perl->new( "rmote_machine"); sorry, I must have failed to mention that I'm using Net::SSH2, not Net::SSH::Perl -Jeremy |
From: Charles S B. <cb...@jc...> - 2009-04-06 16:02:40
|
Here is one of my SSH2 testing scripts. It should provide you with the routines you're after. If not, let me know and I might be able to help you further. Cut and paste into your editor of choice... Thanks! Chuck e-mail: cb...@jc... http://www.linkedin.com/in/chuckbrowntx - - - - - - - - SCRIPT BEGIN - - - - - - - - #!/usr/bin/perl ######################################################################## ####### # Script Name: test-ssh2.pl ######################################################################## ####### #use warnings; #use strict; use Net::SSH2; use Data::Dumper; # Version my $ver = "1.2b"; # Cisco Info my $host = "hostname_or_IP_here"; my $username = "username_here"; my $password = "password_here"; my $command1 = "show users"; my $command2 = "show ssh"; my $command3 = "show ntp status"; # Display Version print "VERSION: $ver\n"; # Create new SSH2 object my $ssh2 = Net::SSH2->new(); # Enable Debug #$ssh2->debug(1); # Create a connection to conduct the SSH2 protocol $ssh2->connect($host) or die "Unable to connect Host $@ \n"; # Determine what type of authentication methods are available my $authentication_methods = $ssh2->auth_list($username); print "Valid authentication methods for $host are: $authentication_methods\n"; # Authenticate using a password $ssh2->auth_password( $username, $password ) or die "Unable to login $@ \n"; #$ssh2->auth(rank => ['none'],username=>$username) or die "Unable to login $@ \n"; # Verify we are authenticated - Returns TRUE if authenticated my $authenticated = $ssh2->auth_ok; print "Authenticated: $authenticated\n"; # Create a channel object (single channel across our established connection) my $chan = $ssh2->channel(); print "DEBUG: After channel\n"; # - - - Un-Comment The Routine You Would Like To Execute - - - # # The following subroutines work for Cisco and Alcatel # # Execute multiple commands utilizing shell method (method A) #&use_shell_a( $command1, $command2, $command3 ); # Execute multiple commands utilizing shell method (method B) #&use_shell_b( $command1, $command2, $command3 ); # Execute multiple commands utilizing shell method (method C) #&use_shell_c( $command1, $command2, $command3 ); # Execute multiple commands _AND_ pattern match utilizing shell method (method D) &use_shell_d( $command1, $command2, $command3 ); # # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # NOTE: On Solaris 9, you must somehow disconnect from the host or the perl # script seems to hang. You can do this several ways. # 1) least graceful, just disconnect the session. # $ssh2->disconnect(); # # 2) more graceful, issue a 'logout' command to your host (or whatever log-off syntax is required) # print $chan "logout\n"; # $chan->close; # # 3) fancy, check to see if the session has received an eof from the host. if not, then # either perform a graceful logout or just disconnect. # if (! $chan->eof) { # print "EOF _NOT_ found attempting graceful disconnect.\n"; # print $chan "logout\n"; # } # # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # Disconnect from the host print "DEBUG: Right before disconnect\n"; $ssh2->disconnect(); print "DEBUG: After disconnect\n"; # Exit exit; # # SUBROUTINES # sub use_shell_a { # Start a shell on the remote host $chan->shell(); # Cycle through each command provided in the sub-routine call foreach my $command (@_) { # Print the command to the defined shell print $chan "$command\n"; # Print the output while there is some data response print "LINE : $_" while <$chan>; } } sub use_shell_b { # Start a shell on the remote host $chan->shell(); # Cycle through each command provided in the sub-routine call foreach my $command (@_) { # Print the command to the defined shell print $chan "$command\n"; # Print the output while there is some data response while (<$chan>) { print "RESP($command) : $_"; } } } sub use_shell_c { # Start a shell on the remote host $chan->shell(); # Cycle through each command provided in the sub-routine call foreach my $command (@_) { # Print the command to the defined shell print $chan "$command\n"; # Print the output while there is some data response # Note: This is a more succint version of 'use_shell_b' print "RESP($command) : $_" while <$chan>; } print "complete\n"; } sub use_shell_d { # Start a shell on the remote host $chan->shell(); # Cycle through each command provided in the sub-routine call foreach my $command (@_) { # Print the command to the defined shell print $chan "$command\n"; # While there is some data in $chan while (<$chan>) { # Perform a regex match on $_ if (/$username/) { # If a match was found, print the info print "I located my username while executing '$command', matched line:\n"; print "$_\n"; } } } } sub waitfor { ## waitfor ## If you want to print any console data gathered while waiting: ## @returned_data = &waitfor('searchpattern',10); ## print @returned_data; ## Where 10 is the timeout in seconds... ## Otherwise use: ## &waitfor('searchpattern',10); ## my ( $search, $timeout ) = @_; my @lines; my $PatternFound = undef; my $TimedOut = undef; my @formattedoutput = undef; $timeout += time(); until ( $PatternFound || $TimedOut ) { # Map some output @rawoutput = map { $_ } <$chan>; # Search for pattern and format return output foreach $rawline (@rawoutput) { $rawline =~ s/stty: stdin not a tty//g; ## Remove unimportant error on Symbol if ( $rawline =~ /$search/ ) { $PatternFound = 1; } while ( $rawline =~ /\s$/ ) { chop $rawline; } $formattedline = "$rawline<br>"; push( @formattedoutput, $formattedline ); } # Check for timeout if ( time() > $timeout ) { $TimedOut = 1; } } if ($TimedOut) { print "ERROR: Timed-Out while waiting for '$search'\n"; } ##print "DEBUG: TimedOut = $TimedOut<br>"; ##print "DEBUG: PatternFound = $PatternFound<br>"; return (@formattedoutput); } sub print_chan { @output = map { while ( $_ =~ /\s$/ ) { chop $_; } $_ } <$chan>; foreach $line (@output) { $line =~ s/stty: stdin not a tty//g; ## Remove unimportant error on Symbol print "\n$line"; } } sub print_chan_continued { # Will print the output of <$chan> until: # 1) The maximum number of 'press any key' prompts have been encountered # 2) A system command prompt is encountered my $maxpages = 6; my $pages = 0; my $endless_loop = 1; while ($endless_loop) { @output = map { while ( $_ =~ /\s$/ ) { chop $_; } $_ } <$chan>; foreach $line (@output) { $line =~ s/stty: stdin not a tty//g; ## Remove unimportant error on Symbol print "\n$line"; if ( $line =~ /Press any key to continue...or/ && $pages < $maxpages ) { # Gather another page of data print $chan "\n"; $pages++; } elsif ( $line =~ /Press any key to continue/ && $pages >= $maxpages ) { # Printed the maximum number of pages, (q)uit and return. print $chan "q\n"; return; } elsif ( $line =~ /.*>.*$|Logging out.../ ) { # Matched regular prompt, return. ##print "DEBUG: matched regular prompt<br>"; return; } } } } - - - - - - - - SCRIPT END - - - - - - - - > -----Original Message----- > From: Jeremy Kitchen [mailto:ki...@sc...] > Sent: Thursday, April 02, 2009 12:47 PM > To: ssh...@li... > Subject: [Ssh-sftp-perl-users] quick question with regard to exec, take 2 > > I'm trying to write a quick program which will execute a series of > commands on the remote system and get each individual exit status back > from the commands. > > It appears the way to go about doing this is to create a new channel, > exec, get the exit status, destroy the channel, exec, get the exit > status, etc. > > However, I *also* want to grab the output of these commands (stdout and > stderr) in real time, so I'm trying to use poll. > > Now, I could be going about this completely the wrong way. If I am, > please let me know :) > > $channel->shell doesn't seem like it fits for me as I don't think I can > get the exit statuses back from the remote commands being run. > > Here's a bit of what I have so far (which isn't working): > > my $channel = $ssh->channel; > > $channel->exec("sleep 5 && echo 'moo' && sleep 1"); > > print "\n"; > while (1) { > print "loop\n"; > my @poll = ({handle => $channel, events => ['in','err']}); > if ($ssh->poll(500, \@poll)) { > # handle events > } > > print Dumper($poll[0]->{revents}); > } > > > everything is all well and good until the command finishes (after the > sleep 5), when polling completely blocks. Nothing further ever happens. > If I kill the remote sshd process handling the connection (the > user@notty process) then it returns these events: > $VAR1 = { > 'in' => 1, > 'value' => 129, > 'listener_closed' => 1, > 'channel_closed' => 1 > }; > > > Is there some step I'm missing to make this work how I want? > > -Jeremy |
From: Jeremy K. <ki...@sc...> - 2009-04-06 17:29:18
|
Charles S Brown wrote: > Here is one of my SSH2 testing scripts. It should provide you with the > routines you're after. If not, let me know and I might be able to help > you further. Cut and paste into your editor of choice... [snip] > # Start a shell on the remote host > $chan->shell(); nope! ->shell doesn't give me the opportunity to get exit codes back from remote commands. -Jeremy |
From: Charles S B. <cb...@jc...> - 2009-04-06 16:02:44
|
Hmmm, some of the formatting became goofy when I pasted it, retry... Thanks! Chuck e-mail: cb...@jc... office: (972) 431-2030 fax: (972) 531-2030 http://www.linkedin.com/in/chuckbrowntx - - - - - - - - SCRIPT BEGIN - - - - - - - - #!/usr/bin/perl ######################################################################## ####### # Script Name: test-ssh2.pl ######################################################################## ####### #use warnings; #use strict; use Net::SSH2; use Data::Dumper; # Version my $ver = "1.2b"; # Cisco Info my $host = "hostname_or_IP_here"; my $username = "username_here"; my $password = "password_here"; my $command1 = "show users"; my $command2 = "show ssh"; my $command3 = "show ntp status"; # Display Version print "VERSION: $ver\n"; # Create new SSH2 object my $ssh2 = Net::SSH2->new(); # Enable Debug #$ssh2->debug(1); # Create a connection to conduct the SSH2 protocol $ssh2->connect($host) or die "Unable to connect Host $@ \n"; # Determine what type of authentication methods are available my $authentication_methods = $ssh2->auth_list($username); print "Valid authentication methods for $host are: $authentication_methods\n"; # Authenticate using a password $ssh2->auth_password( $username, $password ) or die "Unable to login $@ \n"; #$ssh2->auth(rank => ['none'],username=>$username) or die "Unable to login $@ \n"; # Verify we are authenticated - Returns TRUE if authenticated my $authenticated = $ssh2->auth_ok; print "Authenticated: $authenticated\n"; # Create a channel object (single channel across our established connection) my $chan = $ssh2->channel(); print "DEBUG: After channel\n"; # - - - Un-Comment The Routine You Would Like To Execute - - - # # The following subroutines work for Cisco and Alcatel # # Execute multiple commands utilizing shell method (method A) #&use_shell_a( $command1, $command2, $command3 ); # Execute multiple commands utilizing shell method (method B) #&use_shell_b( $command1, $command2, $command3 ); # Execute multiple commands utilizing shell method (method C) #&use_shell_c( $command1, $command2, $command3 ); # Execute multiple commands _AND_ pattern match utilizing shell method (method D) &use_shell_d( $command1, $command2, $command3 ); # # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # NOTE: On Solaris 9, you must somehow disconnect from the host or the perl # script seems to hang. You can do this several ways. # 1) least graceful, just disconnect the session. # $ssh2->disconnect(); # # 2) more graceful, issue a 'logout' command to your host (or whatever log-off syntax is required) # print $chan "logout\n"; # $chan->close; # # 3) fancy, check to see if the session has received an eof from the host. if not, then # either perform a graceful logout or just disconnect. # if (! $chan->eof) { # print "EOF _NOT_ found attempting graceful disconnect.\n"; # print $chan "logout\n"; # } # # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # Disconnect from the host print "DEBUG: Right before disconnect\n"; $ssh2->disconnect(); print "DEBUG: After disconnect\n"; # Exit exit; # # SUBROUTINES # sub use_shell_a { # Start a shell on the remote host $chan->shell(); # Cycle through each command provided in the sub-routine call foreach my $command (@_) { # Print the command to the defined shell print $chan "$command\n"; # Print the output while there is some data response print "LINE : $_" while <$chan>; } } sub use_shell_b { # Start a shell on the remote host $chan->shell(); # Cycle through each command provided in the sub-routine call foreach my $command (@_) { # Print the command to the defined shell print $chan "$command\n"; # Print the output while there is some data response while (<$chan>) { print "RESP($command) : $_"; } } } sub use_shell_c { # Start a shell on the remote host $chan->shell(); # Cycle through each command provided in the sub-routine call foreach my $command (@_) { # Print the command to the defined shell print $chan "$command\n"; # Print the output while there is some data response # Note: This is a more succint version of 'use_shell_b' print "RESP($command) : $_" while <$chan>; } print "complete\n"; } sub use_shell_d { # Start a shell on the remote host $chan->shell(); # Cycle through each command provided in the sub-routine call foreach my $command (@_) { # Print the command to the defined shell print $chan "$command\n"; # While there is some data in $chan while (<$chan>) { # Perform a regex match on $_ if (/$username/) { # If a match was found, print the info print "I located my username while executing '$command', matched line:\n"; print "$_\n"; } } } } sub waitfor { ## waitfor ## If you want to print any console data gathered while waiting: ## @returned_data = &waitfor('searchpattern',10); ## print @returned_data; ## Where 10 is the timeout in seconds... ## Otherwise use: ## &waitfor('searchpattern',10); ## my ( $search, $timeout ) = @_; my @lines; my $PatternFound = undef; my $TimedOut = undef; my @formattedoutput = undef; $timeout += time(); until ( $PatternFound || $TimedOut ) { # Map some output @rawoutput = map { $_ } <$chan>; # Search for pattern and format return output foreach $rawline (@rawoutput) { $rawline =~ s/stty: stdin not a tty//g; ## Remove unimportant error on Symbol if ( $rawline =~ /$search/ ) { $PatternFound = 1; } while ( $rawline =~ /\s$/ ) { chop $rawline; } $formattedline = "$rawline<br>"; push( @formattedoutput, $formattedline ); } # Check for timeout if ( time() > $timeout ) { $TimedOut = 1; } } if ($TimedOut) { print "ERROR: Timed-Out while waiting for '$search'\n"; } ##print "DEBUG: TimedOut = $TimedOut<br>"; ##print "DEBUG: PatternFound = $PatternFound<br>"; return (@formattedoutput); } sub print_chan { @output = map { while ( $_ =~ /\s$/ ) { chop $_; } $_ } <$chan>; foreach $line (@output) { $line =~ s/stty: stdin not a tty//g; ## Remove unimportant error on Symbol print "\n$line"; } } sub print_chan_continued { # Will print the output of <$chan> until: # 1) The maximum number of 'press any key' prompts have been encountered # 2) A system command prompt is encountered my $maxpages = 6; my $pages = 0; my $endless_loop = 1; while ($endless_loop) { @output = map { while ( $_ =~ /\s$/ ) { chop $_; } $_ } <$chan>; foreach $line (@output) { $line =~ s/stty: stdin not a tty//g; ## Remove unimportant error on Symbol print "\n$line"; if ( $line =~ /Press any key to continue...or/ && $pages < $maxpages ) { # Gather another page of data print $chan "\n"; $pages++; } elsif ( $line =~ /Press any key to continue/ && $pages >= $maxpages ) { # Printed the maximum number of pages, (q)uit and return. print $chan "q\n"; return; } elsif ( $line =~ /.*>.*$|Logging out.../ ) { # Matched regular prompt, return. ##print "DEBUG: matched regular prompt<br>"; return; } } } } - - - - - - - - SCRIPT END - - - - - - - - |
From: Charles S B. <cb...@jc...> - 2009-04-06 16:16:36
Attachments:
test-ssh2.pl.txt
|
Meh, simply attached it... Good luck... Thanks! Chuck e-mail: cb...@jc... office: (972) 431-2030 fax: (972) 531-2030 http://www.linkedin.com/in/chuckbrowntx > -----Original Message----- > From: Charles S Brown > Sent: Monday, April 06, 2009 10:24 AM > To: 'Jeremy Kitchen'; 'ssh...@li...' > Subject: RE: [Ssh-sftp-perl-users] quick question with regard to exec, > take 2 > > Hmmm, some of the formatting became goofy when I pasted it, retry... > > Thanks! > Chuck > > e-mail: cb...@jc... > office: (972) 431-2030 > fax: (972) 531-2030 > http://www.linkedin.com/in/chuckbrowntx > > - - - - - - - - SCRIPT BEGIN - - - - - - - - > > #!/usr/bin/perl > ######################################################################## ## > ##### > # Script Name: test-ssh2.pl > ######################################################################## ## > ##### > #use warnings; > #use strict; > use Net::SSH2; > use Data::Dumper; > > # Version > my $ver = "1.2b"; > > # Cisco Info > my $host = "hostname_or_IP_here"; > my $username = "username_here"; > my $password = "password_here"; > my $command1 = "show users"; > my $command2 = "show ssh"; > my $command3 = "show ntp status"; > > # Display Version > print "VERSION: $ver\n"; > > # Create new SSH2 object > my $ssh2 = Net::SSH2->new(); > > # Enable Debug > #$ssh2->debug(1); > # Create a connection to conduct the SSH2 protocol > $ssh2->connect($host) or die "Unable to connect Host $@ \n"; > > # Determine what type of authentication methods are available > my $authentication_methods = $ssh2->auth_list($username); > print "Valid authentication methods for $host are: > $authentication_methods\n"; > > # Authenticate using a password > $ssh2->auth_password( $username, $password ) or die "Unable to login $@ > \n"; > > #$ssh2->auth(rank => ['none'],username=>$username) or die "Unable to login > $@ \n"; > # Verify we are authenticated - Returns TRUE if authenticated > my $authenticated = $ssh2->auth_ok; > print "Authenticated: $authenticated\n"; > > # Create a channel object (single channel across our established > connection) > my $chan = $ssh2->channel(); > print "DEBUG: After channel\n"; > > # - - - Un-Comment The Routine You Would Like To Execute - - - > # > # The following subroutines work for Cisco and Alcatel > # > # Execute multiple commands utilizing shell method (method A) > #&use_shell_a( $command1, $command2, $command3 ); > # Execute multiple commands utilizing shell method (method B) > #&use_shell_b( $command1, $command2, $command3 ); > # Execute multiple commands utilizing shell method (method C) > #&use_shell_c( $command1, $command2, $command3 ); > # Execute multiple commands _AND_ pattern match utilizing shell method > (method D) > &use_shell_d( $command1, $command2, $command3 ); > > # > # > # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - > # > # NOTE: On Solaris 9, you must somehow disconnect from the host or the > perl > # script seems to hang. You can do this several ways. > # 1) least graceful, just disconnect the session. > # $ssh2->disconnect(); > # > # 2) more graceful, issue a 'logout' command to your host (or whatever > log-off syntax is required) > # print $chan "logout\n"; > # $chan->close; > # > # 3) fancy, check to see if the session has received an eof from the > host. if not, then > # either perform a graceful logout or just disconnect. > # if (! $chan->eof) { > # print "EOF _NOT_ found attempting graceful disconnect.\n"; > # print $chan "logout\n"; > # } > # > # > # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - > # > # Disconnect from the host > print "DEBUG: Right before disconnect\n"; > $ssh2->disconnect(); > print "DEBUG: After disconnect\n"; > > # Exit > exit; > > # > # SUBROUTINES > # > sub use_shell_a { > > # Start a shell on the remote host > $chan->shell(); > > # Cycle through each command provided in the sub-routine call > foreach my $command (@_) { > > # Print the command to the defined shell > print $chan "$command\n"; > > # Print the output while there is some data response > print "LINE : $_" while <$chan>; > } > } > > sub use_shell_b { > > # Start a shell on the remote host > $chan->shell(); > > # Cycle through each command provided in the sub-routine call > foreach my $command (@_) { > > # Print the command to the defined shell > print $chan "$command\n"; > > # Print the output while there is some data response > while (<$chan>) { > print "RESP($command) : $_"; > } > } > } > > sub use_shell_c { > > # Start a shell on the remote host > $chan->shell(); > > # Cycle through each command provided in the sub-routine call > foreach my $command (@_) { > > # Print the command to the defined shell > print $chan "$command\n"; > > # Print the output while there is some data response > # Note: This is a more succint version of 'use_shell_b' > print "RESP($command) : $_" while <$chan>; > } > print "complete\n"; > } > > sub use_shell_d { > > # Start a shell on the remote host > $chan->shell(); > > # Cycle through each command provided in the sub-routine call > foreach my $command (@_) { > > # Print the command to the defined shell > print $chan "$command\n"; > > # While there is some data in $chan > while (<$chan>) { > > # Perform a regex match on $_ > if (/$username/) { > > # If a match was found, print the info > print "I located my username while executing '$command', > matched line:\n"; > print "$_\n"; > } > } > } > } > > sub waitfor { > ## waitfor > ## If you want to print any console data gathered while waiting: > ## @returned_data = &waitfor('searchpattern',10); > ## print @returned_data; > ## Where 10 is the timeout in seconds... > ## Otherwise use: > ## &waitfor('searchpattern',10); > ## > my ( $search, $timeout ) = @_; > my @lines; > my $PatternFound = undef; > my $TimedOut = undef; > my @formattedoutput = undef; > $timeout += time(); > until ( $PatternFound || $TimedOut ) { > > # Map some output > @rawoutput = map { $_ } <$chan>; > > # Search for pattern and format return output > foreach $rawline (@rawoutput) { > $rawline =~ s/stty: stdin not a tty//g; ## Remove > unimportant error on Symbol > if ( $rawline =~ /$search/ ) { > $PatternFound = 1; > } > while ( $rawline =~ /\s$/ ) { chop $rawline; } > $formattedline = "$rawline<br>"; > push( @formattedoutput, $formattedline ); > } > > # Check for timeout > if ( time() > $timeout ) { > $TimedOut = 1; > } > } > if ($TimedOut) { > print "ERROR: Timed-Out while waiting for '$search'\n"; > } > ##print "DEBUG: TimedOut = $TimedOut<br>"; > ##print "DEBUG: PatternFound = $PatternFound<br>"; > return (@formattedoutput); > } > > sub print_chan { > @output = map { > while ( $_ =~ /\s$/ ) { chop $_; } > $_ > } <$chan>; > foreach $line (@output) { > $line =~ s/stty: stdin not a tty//g; ## Remove unimportant > error on Symbol > print "\n$line"; > } > } > > sub print_chan_continued { > > # Will print the output of <$chan> until: > # 1) The maximum number of 'press any key' prompts have been > encountered > # 2) A system command prompt is encountered > my $maxpages = 6; > my $pages = 0; > my $endless_loop = 1; > while ($endless_loop) { > @output = map { > while ( $_ =~ /\s$/ ) { chop $_; } > $_ > } <$chan>; > foreach $line (@output) { > $line =~ s/stty: stdin not a tty//g; ## Remove unimportant > error on Symbol > print "\n$line"; > if ( $line =~ /Press any key to continue...or/ && $pages < > $maxpages ) { > > # Gather another page of data > print $chan "\n"; > $pages++; > } > elsif ( $line =~ /Press any key to continue/ && $pages >= > $maxpages ) { > > # Printed the maximum number of pages, (q)uit and return. > print $chan "q\n"; > return; > } > elsif ( $line =~ /.*>.*$|Logging out.../ ) { > > # Matched regular prompt, return. > ##print "DEBUG: matched regular prompt<br>"; > return; > } > } > } > } > > - - - - - - - - SCRIPT END - - - - - - - - |