Re: Simple hash assignment...or is it?
by delirium (Chaplain) on Nov 22, 2003 at 01:35 UTC
|
One of Perl's cooler selling points is being able to substitute for programs like cut, grep, uniq, and sort by using native Perl functions.
I've rewritten what you have a little (the output is different, but I think I get the gist of what you're trying to do) so that the only shell is for the netstat command.
#!/usr/bin/perl
use strict;
my %adapter_names = ();
for (split /\n/, `netstat -i`) {
next if /lo|sit|link|Name/;
/(\S+)/; # Takes first block of non-spaces, assigns to $1
my $interface = $1;
my $adapter = $interface;
$adapter =~ s/^en/ent/; # Add other substitutions here
$adapter_names{$adapter} = $interface if !defined $adapter_names{$ad
+apter};
}
print "$_ : $adapter_names{$_}\n" for sort keys %adapter_names;
| [reply] [d/l] |
|
|
Yeah...Perl is really cool. As I said before (see above) I come from a functional/procedural background, so that's what my code tends to look like. (Personally, I like parenthesizing... :)
This code is very nice, very clean. I wonder what the speed difference is? I may adopt this style in a later revision (although possibly still pre-production) because the program is part of a stress level monitoring toolkit, with the obvious desire to keep the induced stress as low as possible. So, if I can exec 1 program instead of 5, I lower the induced stress quite a bit.
| [reply] |
Re: Simple hash assignment...or is it?
by mpeppler (Vicar) on Nov 22, 2003 at 01:02 UTC
|
Various things...
First you're using local where I think you mean my. Second, you've got your hash assignment backwards. If you want
foreach (@tcp_utilization_metrics) {
print "$tcp_utilization_adapter_names{$_}\n";
}
to actually print something, then you need to change
$tcp_utilization_adapter_names{"$if_name"} = "$network_if";
to
$tcp_utilization_adapter_names{$network_if} = $if_name;
Michael
| [reply] [d/l] [select] |
|
|
I'm keying my hash on $if_name, not $network_if, because $if_name should be equivalent to one member of @tcp_utilization_metrics, which I use to loop through each value in the hash. Please notice that $if_name is assigned the same value as $network_if at the top of the loop, but $network_if is the variable whose value is changed during the loop.
| [reply] [d/l] [select] |
|
|
Rats - read it backwards :-(
Well - I just ran your code here (on linux), adding "use strict", and adding "my" as appropriate, and it ran correctly (or at least I don't have any empty lines anywhere).
Ah - I know what the problem is:
foreach $network_if (@tcp_utilization_metrics) {
local $if_name = $network_if;
if ($network_if =~ /en/) {
$network_if =~ substr ($network_if, 2, 0, "t");
}
When change the $network_if value here you actually modify the @tcp_utilization_metrics array - see the docs on the behavior of the foreach loop.
If you reverse things you should be fine:
foreach $if_name (@tcp_utilization_metrics) {
local $network_if = $if_name;
if ($network_if =~ /en/) {
$network_if =~ substr ($network_if, 2, 0, "t");
}
That said - you should "use strict" and replace those "local" with "my".
Michael
| [reply] [d/l] [select] |
|
|
Re: Simple hash assignment...or is it?
by Roger (Parson) on Nov 22, 2003 at 00:55 UTC
|
You can use the Data::Dumper module to investigate your hash and array structures.
use Data::Dumper;
...
# insert after the first foreach loop.
print Dumper(\@tcp_utilization_metrics);
| [reply] [d/l] |
|
|
The Dumper output shows me the same thing as my own print statements: that there's some difference between the interface names I'm passing into the foreach block, and what's getting set as hash keys. It's a very confusing problem:
$VAR1 = (
'en0',
'en1'
);
en0: ent0
ent0
en1: ent1
ent1
$VAR1 = {
'en0' => 'ent0',
'en1' => 'ent1'
};
(empty line)
(empty line)
because, as you can see, the hash keys are the same string as the members of the array. | [reply] |
|
|
I have rewritten your code to make it a bit Perl like. The following code is equivalent to your code -
use strict;
use Data::Dumper;
my $network_ifs = `netstat -i | grep -Ev "lo|sit|link|Name" | cut -f1
+-d" " | uniq | sort -n`;
my @tcp_utilization_metrics = split '\n', $network_ifs;
my %tcp_utilization_adapter_names;
foreach my $network_if (@tcp_utilization_metrics) {
next if ! $network_if; # ignore empty lines if any
my $if_name = $network_if;
if ($network_if =~ /en/) {
substr($network_if, 2, 0) = "t"; # insert 't'
} elsif ($network_if =~ /tr/) {
substr($network_if, 1, 2) = "ok"; # replace 'ok'
} elsif ($network_if =~ /at/) {
substr($network_if, 2, 0) = "m"; # insert 'm'
}
# insert hash entries
$tcp_utilization_adapter_names{$if_name} = $network_if;
}
# investigate the hash
foreach (keys %tcp_utilization_adapter_names) {
print "$tcp_utilization_adapter_names{$_}\n";
}
Perhaps you could tell us what is your expected hash output. I highly suspect that you want the following instead in your code (swap the key-value in the hash) -
# insert hash entries
$tcp_utilization_adapter_names{$network_if} = $if_name;
| [reply] [d/l] [select] |
|
|
|
|
|
|
|
Re: Simple hash assignment...or is it?
by delirium (Chaplain) on Nov 22, 2003 at 00:54 UTC
|
How about a description of what you are doing and what the output should look like? | [reply] |
|
|
I'm getting AIX network interface names and transforming them into the corresponding network adapter names. I'm using the interface names as keys, and the adapter names as values in the hash.
| [reply] |
Re: Simple hash assignment...or is it?
by arootbeer (Novice) on Nov 22, 2003 at 06:29 UTC
|
Wow...I can't believe I spaced on this code. I was telling a friend about it, and he kind of looked at me blankly, like "what did you think it was going to do?" This is a case of too long a day... :)
I think I honestly thought that it was giving me the wrong output because the output wasn't what I wanted it to be...
Thanks for all the help to everyone who pitched in to help clear the room of my brain fart! | [reply] |
|
|
It appears that you are attempting to collect protocol statistics for network adapters.
If this is the case, there are several readymade, free tools that are more suited to that task, and can perform it far more efficiently, and in "standard" manner, with oh-so-many more features. Most of these tools involve SNMP, and if you have not seen MRTG yet, check out http://mrtg.org
| [reply] |
|
|
Well, in my current assignment, I've been asked to do it using only AIX command line calls. Don't ask...
Personally, I was going to use PTX, which is a VERY fully featured AIX Performance monitoring and reporting solution, but this is the way I was asked to do it, so this is the way it must be...
I will check out the site you mentioned; thanks for the heads-up!
| [reply] |