DarthBobToo has asked for the wisdom of the Perl Monks concerning the following question:
Oh wise and all-knowing gurus...
I am writing a module using Moose that will serve as a wrapper to Net::SSH2 to log into an appliance, grab system information, and return it back to the caller for system monitoring purposes.
My issue is around references. In my module, references aren't working as I would expect them to. I have created a simplified version of the module that replicates the issue to include here.
Here is the code, below. However, please look at lines 125-126 and 131-134 (in the execute() method). If I use the code as pasted here, everything works both hunky and dory. It returns the output of the command run on the appliance as expected. However, if I uncomment lines 125,131-132 and comment out lines 126,133-134, it fails, usually telling me that line 133 is not a GLOB reference. What am I doing wrong?
Thanks.
package Foo; use v5.14; use strict; use warnings; use Carp; use Moose; use MooseX::StrictConstructor; use Net::SSH2; has 'hostname' => ( isa => 'Str', is => 'rw', ); has 'username' => ( isa => 'Str', is => 'rw', ); has 'password' => ( isa => 'Str', is => 'rw', ); has 'command' => ( isa => 'Str', is => 'rw', ); has '_ssh2_connection' => ( is => 'bare', isa => 'Object', ); has '_ssh2_channel' => ( is => 'bare', isa => 'Object', ); ## # Connect to server using provided parameters. # sub connect { my $self = shift; ## # Net::SSH2 connection object. # my $connection = Net::SSH2->new(); # Connect to server. $connection->connect($self->hostname()) or croak "Unable to connect to " . $self->hostname() . ": +$@\n"; $connection->auth_password($self->username(),$self->password()) or croak "Unable to authenticate to " . $self->hostname() . " as " . $self->username . ": $@\n"; ## # Net::SSH2::Channel object. # my $channel = $connection->channel(); # Open Net::SSH2::Channel shell so that multiple commands # can be executed. $channel->blocking(0); $channel->shell(); # Manually flush channel. Uncertain why this must be done, but # when used in an object wrapper, execute() will fail later if # it is not. using $channel->flush() doesn't do the trick. print $channel "\n"; while (<$channel>) { chomp; push my @tmp,"$_\n"; } # Attach connection and channel to object. $self->{_ssh2_channel} = \$channel; $self->{_ssh2_connection} = \$connection; return 1; } ## # Disconnect from server. # sub disconnect { my $self = shift; # Close Net::SSH2 objects. ${$self->{_ssh2_channel}}->close() if (defined ${$self->{_ssh2_cha +nnel}}); ${$self->{_ssh2_connection}}->disconnect() if (defined ${$self->{_ +ssh2_connection}}); # Delete Net::SSH2 objects. $self->{_ssh2_channel} = undef; $self->{_ssh2_connection} = undef; return 1; } ## # Execute command specified by 'command' attribute. # sub execute { # Initialize variables. my $self = shift; #my $channel = ${$self->{_ssh2_channel}}; my $channel = $self->{_ssh2_channel}; my @return_data; my $cmd = $self->command(); # Execute command and process return data. #print $channel "$cmd\n"; #while (<$channel>) { print {${$channel}} "$cmd\n"; while (<${$channel}>) { chomp; push @return_data,"$_\n"; } # Return array ref to caller. return \@return_data; } 1; # End of module. __PACKAGE__->meta->make_immutable; __END__
...and here is a test file, if you'd like to use it...
use v5.14; use strict; use warnings; use Foo; # Define object parameters. use constant { HOSTNAME => 'host.example.com', USERNAME => 'username', PASSWORD => 'password', COMMAND => 'ls -la', }; # Create the object. my $rt = Foo->new({ hostname => HOSTNAME, username => USERNAME, password => PASSWORD, command => COMMAND, }); # Connect to server and execute. $rt->connect(); my $rv = $rt->execute(); $rt->disconnect(); # Print the results. print "$_" foreach (@{$rv}); print "*** DONE ***\n";
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Question regarding using references with Net::SSH2 in module
by Preceptor (Deacon) on Jun 14, 2013 at 20:58 UTC |