Re: redirect stdout into hash
by zentara (Cardinal) on Jun 13, 2012 at 17:40 UTC
|
Why do you need a hash? An array might be simpler. With a hash, you will need to increment a hash key counter, whearas with an array, you just keep pushing each recv into the array in order received. Anyways, for a hash, something like this would work. There is one glitch, since you are reading a $buf of size 1024, you have no idea where the newlines are going to be, so each hash entry may be an incomplete line, which is continued in the next hash entry. It may be better to concantate all received $buf into one long string, then split the string on newlines at put those lines into a hash.
use warnings;
use Net::SSH2;
use Data::Dumper;
my $ssh = Net::SSH2->new();
# make a global hash for storage
my %hash;
# make a global counter for incrementing the hash keys
my $counter = 0;
......
......
if($ssh->auth_ok())
{
runcmd(my_channel($ssh), "$bigcmd");
}
# read output ( but lines may be split )
print $DATA::Dumper( \%hash ),"\n";
__END__
sub runcmd
{
my ($channel, $command) = @_;
$channel->exec($command);# or die $@ . $ssh->error();
my $buff;
while(!$channel->eof())
{
my $buff;
$channel->read($buff, 1024);
# print $buff;
$hash{$counter} = $buf;
$counter++;
}
my $rc = $channel->exit_status();
$channel->close();
return $rc;
}
| [reply] [d/l] |
|
|
Its seems everyone is right that an array may be easier. For memory efficiency, what is the best way to pipe the output into an array?
| [reply] |
|
|
If you want to change from hash, a concated scalar string is probably your best bet, unless you need an array of lines.Here is how to do either way.
# make a global array for storage
my @array;
#or make a global scalar string
my $storage_string;
.....
.....
while(!$channel->eof())
{
my $buff;
$channel->read($buff, 1024);
# print $buff;
push @array, $buf; # pushes $buf into next array slot
# or use a concated string
$storage_string .= $buf; # concantates $buf onto end of stri
+ng
}
When you want to read the array, you have a couple of options. Since your newlines may still be out of place, you may get staggered lines, but if you print
the array it may reassemble itself properly
$/ = ''; # change output separator to nothing instead of newline
print @array, "\n";
but this just recreates a string with embedded newlines
If you go with the concated string route, you can easily split on newlines:
my @lines=split( /\n/, $storage_string);
print "@lines\n";
# or since $storage_string contains embedded newlines, just printing i
+t would work
print "$storage_string\n";
Either way, an array joined with the output separator set to '', or a concated string
split on newlines should give good results.
| [reply] [d/l] [select] |
|
|
Re: redirect stdout into hash
by MidLifeXis (Monsignor) on Jun 13, 2012 at 17:40 UTC
|
Where you are reading the data (the while ! eof section is probably where you want to do this. Instead of the print command, you would load it into a buffer for processing it into a hash.
The way that you are reading the text from $bigcmd will not give you data in any structured form, but just as a string of at most 1024 characters at a time. You will probably want to join the strings together, split them into the actual records (or use regular expressions), and then push them into a data structure.
One thing that may help get some more help on this is to list a small snippet of what the output looks like, as well as how the resulting output string should look.
Update: As zentara has also stated, if you are just looking to have a set of lines, and not structured data, reading the data into an array is likely a better option.
| [reply] [d/l] [select] |
|
|
WAFFINITY_NVLOG_COMPLETION = 170613544 0 0 169894032
FREE_CACHE_REFILL = 6071 35904 35904 22483
PURGE_FILE_PURGE = 173463 27149 27149 0
BUF_CACHE_REBALANCE = 27438 4841 4841 0
_WAFL_BACKDOOR = 85407891 10800645 10800645 0
==================== = ======== ======== ======== ========
Totals = 645100944 11046000 11046000 799567928
msg_cnt (since boot) = 656146947
wafl restart count histogram: (432440632) -- simple counts
0 1 2 3 4 5 6
+ 7
429360452 2285980 67923 2963 5226 10431 432485 82
+144
<16 <24 <32 <40 <48 <56 <64 UNUS
+ED
135096 22222 9999 4529 2296 1869 1820
+ 0
<128 <192 <256 <320 <384 <448 <512 UNUS
+ED
7676 2625 1233 718 2225 718 2
+ 0
Odd number of elements in hash assignment at ./waflsusp.pl line 36.
<1024 <1536 <2048 <2560 <3072 <3584 <4096 UNUS
+ED
0 0 0 0 0 0 0
+ 0
<8192 <12288 <16384 <20480 <24576 <28672 <32768 UNUS
+ED
0 0 0 0 0 0 0
+ 0
<65536 <98304 <131072 <163840 <196608 <229376 <262144 >2621
+44
0 0 0 0 0 0 0
+ 0
Average: 0.02
Later I will be pulling various elements out of this data for evaluation. For example, there may be three fields retrieved by name where I need to perform some math on their values.
Example:
mycache-hit = 1000
mycache-miss = 410
mycache-miss-why = 309
410/1000 = X, 309/410 = Y, etc etc
| [reply] [d/l] |
Re: redirect stdout into hash
by aaron_baugher (Curate) on Jun 13, 2012 at 18:51 UTC
|
Since the Net::SSH::Channel object is also a tied filehandle, you can avoid all the C-style read buffering:
$channel->exec($command);
my @array = <$channel>; # read output lines into an array
# or
my %hash = map { $_ => undef } <$channel>; # read output lines into a
+hash's keys
Aaron B.
Available for small or large Perl jobs; see my home node.
| [reply] [d/l] |
|
|
Thanks, but the array doesn't seem to be populating when used in the subroutine?
| [reply] |
|
|
| [reply] [d/l] [select] |
|
|
|
|