getwithrob has asked for the wisdom of the Perl Monks concerning the following question:

I was given a perl script that will read Cisco device hostnames from a text file then snmp query different values against those devices and write the output to a .csv file. The values I want to query are ifDescr, ifOperStatus, ifAdminStatus, ifLastChange. See the “my @columns” section in the first line or two. Here's the problem I have. The script appears to walk all values but only writes the first row of output to the .csv file. Can someone help me out here? Oh yea. My programming skills are weak at best…..especially in perl!
#!/usr/bin/perl my @columns = qw/interfaces.ifTable.ifEntry.ifDescr interfaces.ifTable +.ifEntry.ifAdminStatus interfaces.ifTable.ifEntry.ifOperStatus interf +aces.ifTable.ifEntry.ifLastChange/; my $CSV = "/opt/home/johnsonr/scripts/output.csv"; my $NODES = "/opt/home/johnsonr/scripts/nodes"; # use strict 'vars'; use Getopt::Std; use vars qw/ %opt /; my (%snmpwalk); my ($csv, $nodes, $tmp, $i, $x, $nam, $val, $node); my ($opt_d, $opt_c, $opt_n, $debug, $column, $node, $line); getopts ('dc:n:',\%opt) or &usage; $debug = $opt{d} ? 1 : 0; $csv = $opt{c} ? $opt{c} : $CSV; $nodes = $opt{n} ? $opt{n} : $NODES; print "nodes=$nodes\n"; sub usage() { print STDERR << "EOF"; This program read a nodes files and creates a csv file with snmp v +alues for each node. usage: $0 [-d] [-c:csv_file] [-n:nodes_file] [test-input-file-jus +t-for-demo] -d : print debugging messages to stderr -c : csv output file name. Default $CSV -n : nodes input file name. Default $NODES EOF exit; } open (NODES, "<$nodes") or die "could not open nodes file $nodes"; + open (CSV, ">$csv") or die "could not open scv file $csv"; + $tmp = join(",",@columns); print CSV "$tmp\n"; while (<NODES>) { chop; $node = $_; $line = ""; print "- $node\n" if $debug; foreach $column (@columns) { $_ = `snmpwalk $node VER143r $column`; if (/=\s*(.*)$/) { $val = $1; } else { $val = "???"; } $line .= $val . ","; print "-- $column, $val\n" if $debug; } chop $line; print CSV $line."\n"; }

2005-09-23 Retitled by g0n, as per Monastery guidelines
Original title: 'Can someone help???'

Replies are listed 'Best First'.
Re: Writing SNMP walk to CSV file
by traveler (Parson) on Sep 22, 2005 at 20:05 UTC
    If the problem is that you are only getting one interface per device, this is the programmed behavior. Your outer loop while (<NODES>) processes each device. Your inner loop (foreach $column) strips one value out of the output of the snmpwalk. The print at the end of the loop prints that one value.

    If the device has more than one device, you'll need to get all the values from the snmpwalk output. Each should be on its own line and it might look like:

    interfaces.ifTable.ifEntry.ifDescr.1 = STRING: Ethernet1 interfaces.ifTable.ifEntry.ifDescr.2 = STRING: Ethernet2 interfaces.ifTable.ifEntry.ifDescr.3 = STRING: Serial0
    Code something like this untested example (I don't have any SNMP devices with multiple interfaces at this office):
    my %values; foreach $column (@columns) { # get all the values for $column for $node $values{column} = [`snmpwalk $node VER143r $column`]; foreach (@($values{column})){ if (/=\s*(.*)$/) { $val = $1; } else { $val = "???"; } $_ = $value; } } # now we have all of each column foreach my $row (0..$#( $values{$columns[0]}}){ foreach my $col (keys %values){ #(for each column) my $line = ""; $line .= $values{$col}[$row] . ","; } print "-- $row, $val\n" if $debug; } chop $line; print CSV $line."\n";
    The code is untested and maybe broken, but the idea should get you started.
      Traveler, I see what you're stating. Can you help me a little more? I stink when it comes to programming. Can you give me a few more hints?
        unless the code is buggy, replace the section in your code that this replaces, beginning with the foreach. It should work.
Re: Writing SNMP walk to CSV file
by CountZero (Bishop) on Sep 22, 2005 at 19:56 UTC
    At first glance I did not find any glaring errors in the script? There are certainly some lines which could be improved or put more in line with current good Perl practices, but that is besides the point.

    Could it be that the problem is in the data? If you have only one line in your output.csv it is probably the header line with the names of the values you check. If my guess is correct, then your NODES file must be empty which stops the while loop from executing even once.

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

      There is one device in the nodes file. The output does in fact have 2 lines the first of those being the header row and the second is the only real line of code. I can snmpwalk on any of those variables and there are several lines of code returned doing it manually. When the script runs against 3 or 4 devices it takes a couple of minutes more to execute so I'm sure it's polling everything but just not writing it to a file.
        When you run it with the debug-option enabled, what output do you get? Can you post it here?

        CountZero

        "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: Writing SNMP walk to CSV file
by runrig (Abbot) on Sep 22, 2005 at 18:01 UTC
    Do you close the filehandle? Granted, the file should be automatically closed when the script exits, but just in case the buffer doesn't get flushed, you should explicitly close it yourself.
      How do I do this. Remember, I'm not a programmer....
        Follow the helpful link. Or:
        close NODES; close CSV;