This is the top result when googling this question, but none of the answers present in this thread (or any other resources I was able to find) resolved my issue so I wanted to contribute my solution.
import paramiko as pm
import time
USER = "user"
PASSWORD = "password"
HOST = "host"
client = pm.SSHClient()
client.set_missing_host_key_policy(pm.AutoAddPolicy())
client.connect(HOST, username=USER, password=PASSWORD)
channel = client.get_transport().open_session()
channel.invoke_shell()
commands = [
"command1",
"command2",
"command3"
]
for cmd in commands:
channel.send(cmd + "\n")
wait_time = 0
while wait_time <= 5:
if channel.recv_ready():
out = channel.recv(1024).decode('utf-8')
print(out)
else:
time.sleep(1)
wait_time += 1
channel.close()
client.close()
I would say this answer is most similar to the one provided by @nagabhushan, but I had issues with deploying child threads to handle processing the stdout of each command. My method is fairly compact and makes it easy to wrap into a function that accepts inputs for user, password, host, and a list of commands.
The biggest point that I haven't seen emphasized in other posts is that (on the servers I tested with) the channel.send(cmd) method needs to be instantly received via channel.recv() or else the subsequent commands will not be executed. I tested this on a Dell switch and an Ubuntu server, which both exhibited the same behavior. Some resources online have examples showing multiple channel.send() executions without receiving the output, and I was unable to get that working on any target device. It's worth noting that the Dell switch OS is built on Ubuntu, so this may be an Ubuntu-architecture specific issue.
As mentioned in other sources (but worth reiterating) the exec_command() method creates a new shell for each execution. If you have a series of commands that must be executed in a single shell session, exec_command() will not work.