1

I'm trying to make a script that makes a connection via ssh to a cisco switch, and right there makes two pings one after the other.

The problem is when I'm doing it - the output in the second ping is "SSH session not active". The quick solution is to make connection -> ping, and then make second connection and ping, but I want to do two pings in one connection.

Right now i have this code:

import paramiko
import time


def connect_ssh(ip, username, password):
    ssh = paramiko.SSHClient()
    try:
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(ip, 22, username, password, timeout=5)
        return ssh, "OK"
    except Exception as e:
        return None, f"ERROR: {str(e)}"


def remote_ping(ssh, host):
    try:
        stdin, stdout, stderr = ssh.exec_command(f"ping  {host}")
        stdout.channel.recv_exit_status()
        response = stdout.read().decode()
        return "OK" if "Success rate is 100 percent" in response else "ERROR"
    except Exception as e:
        return f"ERROR: {str(e)}"


ip = '172.16.1.1'
username = 'a'
password = 'a'

ssh, result_ssh = connect_ssh(ip, username, password)
if ssh:
    result_first_ping = remote_ping(ssh, '8.8.8.8')
    result_second_ping = remote_ping(ssh, '8.8.4.4')
    ssh.close()
else:
    result_first_ping = "SSH_FAILED"
    result_second_ping = "SSH_FAILED"

print(f"First ping result: {result_first_ping}")
print(f"Second ping result: {result_second_ping}")


I've tried doing sleep after the first ping, I've also tried doing it in subprocess and that didn't work as well, but I'm not an expert in that and that may be the right way to do it.

0

1 Answer 1

1

Your code is correct overall for a properly implemented SSH server.

But (at least some) Cisco routers are known not to support multiple "exec" channels over one SSH session.

Solutions are:

  • Reopen the session for each command. While inefficient, it's a reliable approach.

  • If the inefficiency is not acceptable, you can use a shell channel like:

    channel = ssh.invoke_shell()
    channel.send('command 1\n')
    channel.send('command 2\n')
    channel.send('command 3\n')
    while not channel.recv_ready():
        time.sleep(3)
    out = channel.recv(9999)
    print out
    

    But that's not reliable. It is difficult tell when an output of one command finishes and the other starts. It is also difficult tell, if you got all output already or not. And as Paramiko always uses PTY, you get a lot of unwanted output, like prompts, command echoes, etc.


See also What is the difference between exec_command and send with invoke_shell() on Paramiko?

2
  • Thank you, that completes my question. But do you think netmiko will be better in this situation? As far as i know netmiko has no problem with sending two commands in one connection.
    – Seggenz
    Commented Jul 24 at 12:52
  • I have no experience with netmiko. But as the imitation is on the server-side, if netmiko works, it must be internally doing that my answer suggests. Commented Jul 24 at 15:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.