'Paramiko SSH execute command gets stuck at session.recv_exit_status()
Below is my Python code which was running good till either I tried to source some environment variables with an alias. Since then it started hanging at session.recv_exit_status() and now even refuses to execute ls command.
#!/usr/bin/env/python
import paramiko
trans = paramiko.Transport(('fcd01.force.com',22))
trans.connect(username = 'user',password = 'pwd')
session = trans.open_channel("session")
session.exec_command('ls')
session.recv_exit_status() # ** hangs **
while True:
if session.recv_ready():
break
time.sleep(2)
session.send('exit\n')
stdout_data = []
try:
part = session.recv(4096)
while part:
stdout_data.append(part)
part = session.recv(4096)
except:
raise
print 'exit status: ', session.recv_exit_status()
print ''.join(stdout_data)
Any clue how to get ahead?
Solution 1:[1]
I have gotten around hanging by putting connections and executing commands in functions due to the following SO post: Why does Paramiko hang if you use it while loading a module?
As far as the code is concerned, you need to explicitly close your connections using try-catches for example:
try:
session.exec_command("ls")
except **some paramiko exception**:
session.close()
However, your code could be simplified by using the SSHClient.
import paramiko
ssh = SSHClient()
ssh.set_missing_host_key_policy(AutoAddPolicy())
ssh.connect(username="user", password="pwd", hostname="fcd01.force.com", port=22)
try:
stdin, stdout, stderr = ssh.exec_command("ls")
except SSHException:
ssh.close()
else:
**do something with stdout then close the connection**
Using that while loop and getting the bytes back is better if you're looking for an interactive terminal where you're expecting specific prompts to signal for more input, for example PowerBroker access (sudo access). If you're sending just one command and getting a response, and then another command and getting a response, each command not waiting on the prompt of another over the server, you definitely don't need to be reading the data transferred back in blocks.
Also, keep in mind the SSHClient's exec_command() actually closes the underlying transport once complete, and creates a new one every time. You always need to explicitly close the ssh connection.
Solution 2:[2]
Yes, while trying to run an interactive session I messed up with the ssh connection. Now its permanently locked. Here is the output when I run through command line.
*** Python 2.7.9 (default, Dec 10 2014, 12:24:55) [MSC v.1500 32 bit (Intel)] on win32. ***
*** Remote Python engine is active ***
>>> import paramiko
>>> ssh = paramiko.SSHClient()
>>> print ssh
<paramiko.client.SSHClient object at 0x02EEDB10>
>>> print ssh.get_transport()
None
>>> ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
>>> ssh.connect('fcd01.force.com',username = 'user',password = 'pwd')
>>> print ssh
<paramiko.client.SSHClient object at 0x02EEDB10>
>>> print ssh.get_transport()
<paramiko.Transport at 0x2ef8f90L (cipher aes128-ctr, 128 bits) (active; 0 open channel(s))>
>>> print ssh.get_transport().is_active()
True
>>> ssh.exec_command('ls')
(<paramiko.ChannelFile from <paramiko.Channel 0 (open) window=2097152 -> <paramiko.Transport at 0x2ef8f90L (cipher aes128-ctr, 128 bits) (active; 1 open channel(s))>>>,
>>, >>)
print ssh
If I do stdin, stdout stderr = ssh.exec_command('ls') and then print stdout.readlines(), PyScripter hangs (or even if I run the script from command prompt, it hangs). It seems I first need to disconnect or close existing connections with the server which I dont know how to do.
The output of ssh.exec_command('ls') was printed thrice (3 times) in Pyscripter, it got pasted only once here.
Solution 3:[3]
There is a possibility of hanging if the remote output exceeds certain values, as per the Paramiko Documentation. The solution is also specified there:
Warning In some situations, receiving remote output larger than the current Transport or session’s window_size (e.g. that set by the default_window_size kwarg for Transport.init) will cause recv_exit_status to hang indefinitely if it is called prior to a sufficiently large Channel.recv (or if there are no threads calling Channel.recv in the background).
In these cases, ensuring that recv_exit_status is called after Channel.recv (or, again, using threads) can avoid the hang.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Community |
| Solution 2 | user3565150 |
| Solution 3 | Evan L |
