Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

For each loop through mysql db to run Net::Telnet command

by jay83 (Novice)
on Oct 21, 2022 at 15:25 UTC ( [id://11147574]=perlquestion: print w/replies, xml ) Need Help??

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

I am attempting to cycle through my db table list of 5 servers and run the same command for each server to collect and print all the results to the browser through a php script. This is my first work with perl! Here is my code:

#!/usr/local/bin/perl use warnings; use Net::Telnet(); # MySQL database configuration //BELOW DB CONNECTION TEST IS WORKING A +ND CONNECTED. JB 20220930 15:25 use DBI; #---------------------------------------------------------------- # Execute a command on a Zhone device #---------------------------------------------------------------- sub zhoneCommand($$) { my ($command, @output, $session); ($session, $command)=@_; @output=$session->cmd(String => "$command", Errmode => 'return'); chomp @output; return(@output); } #---------------------------------------------------------------- # Connect to a Zhone device via telnet session #---------------------------------------------------------------- sub zhoneConnect($) { my ($device , $session); ($device)=@_; $session = new Net::Telnet(Host=> "$device", Prompt => '/>\s*/', Tim +eout => 10, Errmode => 'return', Output_record_separator => "\n\r"); $session->input_log("log_$device") if ($session && ($DEBUG)); return($session); } #---------------------------------------------------------------- # Disconnect from Zhone device #---------------------------------------------------------------- sub zhoneDisconnect($) { my ($session); ($session)=@_; if ($session) { $session->cmd("logout"); $session->close(); } } #---------------------------------------------------------------- # Login to a Zhone device #---------------------------------------------------------------- sub zhoneLogin($$$) { my ($password, $session, $user); ($session, $user, $password)=@_; return($session->login("$user","$password")); } #---------------------------------------------------------------- # Globals #---------------------------------------------------------------- $DEBUG=1; #---------------------------------------------------------------- # Main Program #---------------------------------------------------------------- ##################### PERLMONKS QUESTION STARTING HERE ############### +########### $dsn = "DBI:mysql:bfcma:localhost"; $username = "root"; $password = 'password'; $dbc = DBI->connect($dsn, $username, $password) or die "Unable to conn +ect to mysql: $DBI::errstr\n"; #//loop through the servers table to pull data for each server $sql = $dbc->prepare("SELECT server_host FROM servers"); $result = $sql->execute(); or die "Unable to execute sql: $sql->errstr"; while (my @row = $sql->fetchrow_array()) { #print "@row\n"; } foreach $host (@row) { $device= $host; $user="username"; $password="password"; STDOUT->autoflush; die "Unable to telnet to device\n" if (! ($session=zhoneConnect($devic +e))); die "unable to login to device\n" if (! zhoneLogin($session, $user, $p +assword)); zhoneCommand($session, "timeout off"); zhoneCommand($session, "setline 0"); $session->prompt('/\n\rAUTO>\s*/'); zhoneCommand($session, "setprompt session AUTO>\r"); @output=zhoneCommand($session, "bridge show"); for (@output) { print "$_\n"; } zhoneDisconnect($session); #close while loop }

Replies are listed 'Best First'.
Re: For each loop through mysql db to run Net::Telnet command
by Bod (Parson) on Oct 21, 2022 at 18:01 UTC

    Firstly, add use strict; to turn on strictures as well as warnings

    The condition in your while loop - my @row = $sql->fetchrow_array() will load the columns from one row of your database into the array. The next call to fetchrow_array will return the next row until there are no more rows when it returns undef.

    So, you need to put your call to telnet in that loop

    As it is, you are pulling the list of server_host from the DB and doing nothing with them! By the time the loop exits, you have an undefined value instead of a host value

      Great thank you for that help!
Re: For each loop through mysql db to run Net::Telnet command
by Marshall (Canon) on Oct 22, 2022 at 08:20 UTC
    Echoing previous post, you should "use strict;"

    Do not use function prototypes. This turns out to be a bad idea although it looks familiar from other languages. There is reason for them, but this is not it.

    Once you have done that, I could move the main loop part of the code to the front and put the subs at the end.
    I recoded one sub for you.

    #---------------------------------------------------------------- # Execute a command on a Zhone device - recoded***** #---------------------------------------------------------------- sub zhoneCommand { my ($command,$session) = @_; #<- look at this line for I/F my @output=$session->cmd(String => "$command", Errmode => 'return'); chomp @output; return(@output); } #-------------- I would use fetchall_arrayref for a small, simple result set like this +. You get a reference to an array of server_host's. Then just iterate over that array. #--------------------- # loop through the servers table to pull data for each server my $sql = $dbc->prepare("SELECT server_host FROM servers"); my $result = $sql->execute(); or die "Unable to execute sql: $sql->errstr"; my $host_array_ref = $result->fetchall_arrayref() or die "can't get a +rray ref! $sql->errstr"; foreach my $rowref (@$host_array_ref) { my ($host) = @$rowref; print "Calling telenet stuff for $host\n"; #a little debugging o +utput is fine # call your telenet routine on this host }

      Thank you - I made edits to the main loop but the error in the terminal is : Can't locate object method "fetchall_arrayref" via package "2" (perhaps you forgot to load "2"?) at filepath line XXXXXXXXXX

      my $dbc = DBI->connect($dsn, $username, $password) or die "Unable to c +onnect to mysql: $DBI::errstr\n"; #//loop through the servers table to pull data for each server my $sql = $dbc->prepare("SELECT server_host FROM servers"); my $result = $sql->execute() or die "Unable to execute sql: $sql->errstr"; XXXX ERROR LINE XXXXX my $host_array_ref = $result->fetchall_arrayref( +) or die "can't get array ref! $sql->errstr"; XXXXXXXXXX foreach my $rowref (@$host_array_ref) { my ($host) = @$rowref; print "Calling telenet stuff for $host\n"; #a little debugging ou +tput is fine # call your telnet routine on this host my $device = $host; my $user = "admin"; my $password = "zhone"; STDOUT->autoflush; die "Unable to telnet to device\n" if (! (my $session=zhoneConnect($de +vice))); die "unable to login to device\n" if (! zhoneLogin($session, $user, $p +assword)); zhoneCommand($session, "timeout off"); zhoneCommand($session, "setline 0"); $session->prompt('/\n\rAUTO>\s*/'); zhoneCommand($session, "setprompt session AUTO>\r"); my @output=zhoneCommand($session, "bridge show"); for (@output) { print "$_\n"; } zhoneDisconnect($session); }

        Hi,

        You are trying to call fetchall_arrayref on the return value of your execute() call. In fact it is a method on the statement handle, which in your code is $sql (more idiomatically named as $sth).

        Hope this helps!


        The way forward always starts with a minimal test.
        Yeah, there are some cut-n-paste errors above. Unfortunately you didn't provide a complete example for me to test my code with.

        First suggestion is to get rid of the "or die" statements, by specifying the raise error option during the dB connect. A little short of time this morning, but the below is some actual working code from a few days ago on an SQLite DB. I use $dbh for the data base handle. You can follow this pattern.

        my %attr = ( RaiseError => 1); #auto die with error printout my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfilename","","",\%attr) or die "Couldn't connect to database $dbfilename: " . DBI->errstr; my $get_qsos = $dbh->prepare ("SELECT * FROM raw_qsos WHERE rcv_call = ?"); $get_qsos->execute($call); my $resultRef = $get_qsos->fetchall_arrayref; my $n_dbQso = scalar(@$resultRef); #number of rows with that call
Re: For each loop through mysql db to run Net::Telnet command
by jay83 (Novice) on Nov 14, 2022 at 13:19 UTC

    Thank you all - here is the working code segment:

    #################################### //code this below to loop through + all the servers with DB connection, join all results into one array +#################################### my $dsn = "DBI:mysql:table:localhost"; my $username = "username"; my $password = 'password'; my $dbc = DBI->connect($dsn, $username, $password) or die "Unable to c +onnect to mysql: $DBI::errstr\n"; #//loop through the servers table to pull data for each server my $sql = $dbc->prepare("SELECT server_host FROM server_test"); $sql->execute() or die "Unable to execute sql: $sql->errstr"; my $host_array_ref = $sql->fetchall_arrayref() or die "can't get array + ref! $sql->errstr"; foreach my $rowref (@$host_array_ref) { my ($host) = @$rowref; print "Calling telenet stuff for $host\n"; #a little debugging ou +tput is fine # call your telnet routine on this host my $device = $host; my $user = "user"; my $password = "password"; STDOUT->autoflush; die "Unable to telnet to device\n" if (! (my $session=zhoneConnect($de +vice))); die "unable to login to device\n" if (! zhoneLogin($session, $user, $p +assword)); zhoneCommand($session, "timeout off"); zhoneCommand($session, "setline 0"); $session->prompt('/\n\rAUTO>\s*/'); zhoneCommand($session, "setprompt session AUTO>\r"); my @output=zhoneCommand($session, "bridge show"); for (@output) { print "$_\n"; } zhoneDisconnect($session); }

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11147574]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (3)
As of 2024-04-26 04:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found