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

I am trying to copy a config to a switch from tftp. Everything works fine if I perform the steps manually, which seems to confirm connectivity, IP address, file name(s), tftp server, etc. However, when I run the script it times out at the command $session->cmd("copy tftp start\n -output omitted"); The error indicates a timeout, but I'm not waiting for any prompt matching, which is the most common reason for timeout. I believe it is timing out while waiting the 9 or 10s for the tftp transfer. I have tried using $session->cmd(String => $string, Timeout => 10) with no luck. Also, using $session->always_waitfor_prompt doesn't help, unless I've implemented it wrong. If I weren't bald already, this would certainly make me pull my hair out b/c this isn't anything difficult. Code below:
############# CONNECT TO THE SWITCH AND UPDATE THE CONFIG FILE ####### +################################## my $tftp_server = "172.16.0.100"; my $switch = "172.16.1.2"; my $user = "Cisco"; my $password = "Cisco"; my $dest_file = "startup-config"; my $copy_tftp = "copy tftp start\n$tftp_server\n$config_file\n$dest +_file\n"; #my $matchop = $obj->prompt('/(?m:^\s*--More-- or \(q\)uit/'); # \s matches a whitespace # \S is a negated \s and matches any non-whitespace character [^\s] # ? indicates to match 1 or 0 times, and is placed after the characte +r to match # ^ indicates to match at the beginning of the line # $ indicates to match at the end of the line my $session = Net::Telnet::Cisco->new( Host => $switch, Input_log => "input.log", Output_log => "output.log", Timeout => 30); $session->always_waitfor_prompt; $boolean = $session->ignore_warnings; $boolean = $session->ignore_warnings($boolean); # Wait for the username prompt and enter username @out = $session->waitfor('/Username:.*$/'); print "@out<br>\n"; @out = $session->print($user); print "@out<br>\n"; # Wait for the password prompt and enter the password @out = $session->waitfor('/Password:.*$/'); print "@out<br>\n"; @out = $session->print($password); print "@out<br>\n"; @out = $session->cmd("copy tftp start\n$tftp_server\n$config_file\n$de +st_file\n"); print "@out<br>\n"; @out = $session->cmd("delete vlan.dat\n\n\n"); print "@out<br>\n"; @out = $session->cmd("reload\n\n"); print "@out<br>\n"; @out = $session->close; }
Cheers, Pickles

Replies are listed 'Best First'.
Re: Net Telnet Cisco
by NetWallah (Canon) on Jul 22, 2008 at 16:11 UTC
    I'm not clear on the syntax for the cisco "copy tftp" command, but it seems to me that one of these options should work:
    • Replace the \n by space (Leave \n at the end)
    • Separate the sub commands (split on \n), and feed them individually, in 1-second intervals
    A couple of additional points:
    * You should not need the \n at the end of each line. I's been a while, but there may be an option you could turn on.
    * There IS a debug option to show the Telnet conversation.

    Apologies for incomplete research - I'm at a public computer without complete access.

         Have you been high today? I see the nuns are gay! My brother yelled to me...I love you inside Ed - Benny Lava, by Buffalax

      NetWallah, Not sure about the space before \n - I pulled my single line of code from the example outlined in the doc for Net::Telnet::Cisco of how to copy from the device to a tftp server and it looks essentially identical. How would I send each line in 1s intervals?
Re: Net Telnet Cisco
by jettero (Monsignor) on Jul 22, 2008 at 16:45 UTC
      Paul - Karavelov's answer did not work. I wish I knew why. As I said, this shouldn't be that difficult. I can see that all of my commands are being input by viewing the input and output logs. Their contents are as such:

      INPUT
      User Access Verification

      Username: Cisco
      Password:
      DistrictOffice#copy tftp start
      Address or name of remote host []? 172.16.0.100
      Source filename []? ACES.cfg
      Destination filename startup-config? startup-config
      Accessing tftp://172.16.0.100/ACES.cfg...
      Loading ACES.cfg from 172.16.0.100 (via
      GigabitEthernet0/1): !!
      OK - 6231 bytes
      OK
      6231 bytes copied in 9.320 secs (669 bytes/sec)
      DistrictOffice#

      OUTPUT
      Cisco
      Cisco
      copy tftp start
      172.16.0.100
      ACES.cfg
      startup-config
      reload

      The fact that my final 'reload' command shows up in my output log and not my input log tells me that the 9 or 10s time for the tftp file to download is where this is breaking. I entered a Prompt variable, but I shouldn't have to since Net::Telnet::Cisco already recognizes most prompts. I also have always_waitfor_prompt, but I'm not sure I've specified it correctly. In other words, is the syntax $session->always_waitfor_prompt all that is necessary?

      Current code:
      my $session = Net::Telnet::Cisco->new( Host => $switch, Prompt => '/.*#/', Input_log => "input.log", Output_log => "output.log", Timeout => 30); $session->always_waitfor_prompt; # Wait for the username prompt and enter username @out = $session->waitfor('/Username:.*$/'); print "@out\n"; @out = $session->print($user); print "@out\n"; # Wait for the password prompt and enter the password @out = $session->waitfor('/Password:.*$/'); print "@out\n"; @out = $session->print($password); print "@out\n"; @out = $session->cmd("copy tftp start\n$tftp_server\n$config_file\n$de +st_file\n"); print "@out\n"; @out = $session->cmd("reload\n\n"); print "@out\n"; @out = $session->close;
      Regards, Scott

        Update: I didn't realize where you were timing out. Try session->waitfor('/#/') after the copy command instead of the sleep. That should avoid issues with a long TFTP copy

        Might be a timing\prompt issue. Here's your copy dialog prompt:

        DistrictOffice#copy tftp start

        Address or name of remote host []? 172.16.0.100

        Using session->waitfor('/\?/') might work.

        You should "enable" yourself in order to download the config and issue "reload" command

        I put a sleep 20; inbetween the copy command and reload. It seems to work ok...for now. Scott