2

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?

Rafa Viotti
  • 9,998
  • 4
  • 42
  • 62
user3565150
  • 884
  • 5
  • 21
  • 49
  • Is there a reason you need to retrieve the stdout via bytes? Also what is the error you get when it refuses to execute the ls command? – the_constant Feb 11 '15 at 05:53
  • The code simply hangs at recv_exit_status(), its getting blocked there. – user3565150 Feb 11 '15 at 06:02
  • Well the first thing I'm aware of, is there is an import bug with paramiko where if the code to connect is not in a function, it causes the import to deadlock. see: http://stackoverflow.com/questions/443387/why-does-paramiko-hang-if-you-use-it-while-loading-a-module/450895#450895 – the_constant Feb 11 '15 at 06:06
  • What I understand is my ssh connection is dead locked, I followed your thread and ran the following code, I am still stuck: #!/usr/bin/env/python import paramiko if __name__ == "__main__": ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect('fcd01.force.com',username = 'user',password = 'pwd') stdin,stdout,stderr = ssh.exec_command("pwd") print "here" print stdout.readlines() --- hangs here print stderr.readlines() ssh.close() – user3565150 Feb 11 '15 at 06:27

2 Answers2

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.

Community
  • 1
  • 1
the_constant
  • 681
  • 4
  • 11
  • Hello, I found one issue and removed the deadlock...the issue was when I login to the server, in ~/.bashrc I was doing /bin/bash. There must be some problem if I do /bin/bash and then execute the command. Once I removed that, the code started running properly. But, the ultimate goal is to run a script in bash. I dont know how to proceed, but atleast this problem got over. – user3565150 Feb 11 '15 at 08:03
0

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.

Evan L
  • 91
  • 8