0

I have been trying to collect logs from Cisco switch. The below code works while collecting logs for small outputs like 'show version' etc. But the script hangs when trying to run tech-support.

I have tried using timeout. It collects a small amount of output from stdout but that is just like 2% of the original file size. The code is as below :

commands = {‘env_power’: ‘sh env power’, 'tech_support': 'show tech-support | no-more’}

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
    client.connect(device, username, password)
    for cmd in cmds:
        stdin , stdout, stderr = client.exec_command(commands[i])
        with open(path + i, "wb") as doc:
            doc.write(stdout.read())
            doc.close()
    return True
except Exception as error_str:
    print(error_str)
    return False
finally:
    if client:
        client.close()
Ron
  • 1
  • Where does it hang? Can you retrieve a full output, if you use something like `plink user@host show tech-support | no-more` (or `ssh` instead of `plink`, if you are on Linux). – Martin Prikryl Sep 10 '19 at 19:35
  • Output of where the script hangs. Also the entire tech-support can be downloaded if it try to ssh into it and collect it from there. [INFO] Device_name: Running show tech-support | no-more [DEBUG] [chan 1] Max packet in: 32768 bytes [DEBUG] [chan 1] Max packet out: 32768 bytes [DEBUG] Secsh channel 1 opened. [DEBUG] [chan 1] Sesch channel 1 request ok [DEBUG] [chan 1] Sesch channel 1 request ok – Ron Sep 11 '19 at 01:55
  • Just noticed that the above script is actually working, I was able to collect the entire log (280-300Mb). However it takes a lot of time to collect the logs(20 min approx). Any suggestions on making it faster. Thank you !! – Ron Sep 11 '19 at 02:13

1 Answers1

1
import os
from netmiko import ConnectHandler
from datetime import datetime

password = os.environ["NETMIKO_PASSWORD"]

device = {
    "device_type": "cisco_ios",
    "host": "cisco3.lasthop.io",
    "username": "pyclass",
    "password": password,
}

with ConnectHandler(**device) as net_connect:
    print(net_connect.find_prompt())
    try:
        start_time = datetime.now()
        output = net_connect.send_command("show tech-support")
    finally:
        end_time = datetime.now()
        print(f"\nExec time: {end_time - start_time}\n")

    # Print just the very beginning of the output
    print("\n".join(output.splitlines()[:3])) 

Here you can see that I am executing 'show tech-support'.

On this particular device, 'show tech-support' takes about 75 seconds to execute. Additionally, you can see in the 'send_command()' method call that I have not explicitly specified a read_timeout. Consequently, Netmiko is using the default read_time of ten seconds.

Given the above, we expect this command will fail with an exception after waiting ten seconds.

Note, the code above contains a few special items so that I can track the execution time of send_command() and display this time to the screen.

When we execute this program we see the following:

$ python new_read_timeout.py 
cisco3#

Exec time: 0:00:10.042891

Traceback (most recent call last):
  File "/home/kbyers/pynet/netmiko4/read_timeout/new_read_timeout.py", line 18, in 
    output = net_connect.send_command("show tech-support")
  File "/home/kbyers/netmiko/netmiko/utilities.py", line 600, in wrapper_decorator
    return func(self, *args, **kwargs)
  File "/home/kbyers/netmiko/netmiko/base_connection.py", line 1660, in send_command
    raise ReadTimeout(msg)
netmiko.exceptions.ReadTimeout: 
Pattern not detected: 'cisco3\\#' in output.

Things you might try to fix this:
1. Explicitly set your pattern using the expect_string argument.
2. Increase the read_timeout to a larger value.

You can also look at the Netmiko session_log or debug log for more information.

As expected 'send_command()' fails in ten seconds and it raises an exception (in this case a ReadTimeout exception).

Additionally, Netmiko provides us with some hints on how we might fix the issue (namely increase the 'read_timeout' to a larger value).

try:
    start_time = datetime.now()
    output = net_connect.send_command(
        "show tech-support", 
        read_timeout=90
    )
finally:
    end_time = datetime.now()
    print(f"\nExec time: {end_time - start_time}\n") 

Here you can see that after setting the read_timeout to ninety seconds that the execution worked properly:

$ python new_read_timeout.py 
cisco3#

Exec time: 0:01:17.150191


------------------ show clock ------------------

Drilling into the above behavior a bit more—Netmiko used the 'send_command()' method to execute 'show tech-support'. As part of this method, Netmiko entered a loop searching for either the trailing router prompt or waiting until its read_timeout timer had expired.

After roughly 77 seconds, Netmiko detected the trailing router prompt.

Once it encountered this trailing prompt, Netmiko then returned the command output.

ref. https://pynet.twb-tech.com/blog/netmiko-read-timeout.html

Baris Sonmez
  • 477
  • 2
  • 8