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.
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?