fgimian / paramiko-expect

A Python expect-like extension for the Paramiko SSH library which also supports tailing logs.
MIT License
205 stars 78 forks source link

Paramiko-expect timing out #16

Closed onclericky closed 6 years ago

onclericky commented 7 years ago

Hi,

Today I was developping an application with paramiko-expect, I followed example steps by steps, but I still have an error and I didn't understand where I missed

Here is my code :

`#xxxx : for privacy on the post try: client = paramiko.SSHClient() client.load_system_host_keys() client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

    ipList = open('iplist.txt', 'r')
    cmdList = open('cmdlist.txt', 'r')

    print('Authenticating with public key \'imported-openssh-key\'\nPassphrase for key \'imported-openssh-key\': ', end = '')

    while pwd == 0:
        try :
            password_pk = getpass.getpass('')
            k = paramiko.RSAKey.from_private_key_file(r'C:\Users\decoux\Downloads\decoux@xxxx.rsa', password_pk) 
            pwd = 1
        except:
            print('Wrong passphrase')

    client.connect(hostname, username=username, pkey = k)

    pre_interact = SSHClientInteraction(client, timeout=20, display=True)
    pre_interact.expect('(ex: login@ip) ')                         # HERE IT BLOCK -> each expect blocks the program
    pre_interact.send('xxxxx@x.x.x.x')
    pre_interact.expect('xxxxx@xxxxx:~$ ') 

except Exception:
    traceback.print_exc()
finally:
    try:
        client.close()
    except:
        pass`

Thanks !

fruch commented 7 years ago

@onclericky you might want to use some regular expression to make sure you catch correctly (the space there in the end of '(ex: login@ip) ' might be the issue and the parentheses, try something like '.(ex: login@ip).' (it's a python regex and should escpae parentheses. consider using https://docs.python.org/2/library/re.html#re.escape on you string to make sure it's escaped.

fruch commented 7 years ago

@onclericky is this still an issue for you ? (please close if not)

nanacoding commented 6 years ago

I also have a time out error。

the first interact.expect(PROMPT) is ok, but the second time out。

paramiko version:2.4.0 ssh connect to centos6.8

code

#coding=utf-8
import traceback, re
import paramiko
from paramiko_expect import SSHClientInteraction

def main():
    # Set login credentials and the server prompt
    HOSTNAME = '192.168.1.1'
    USERNAME = 'root'
    PASSWORD = 'aaa'
    PROMPT = '[root@template ~]'
    PROMPT = re.escape(PROMPT)

    # Use SSH client to login
    try:
        # Create a new SSH client object
        client = paramiko.SSHClient()

        # Set SSH key parameters to auto accept unknown hosts
        client.load_system_host_keys()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

        # Connect to the host
        client.connect(hostname=HOSTNAME, username=USERNAME, password=PASSWORD)

        # Create a client interaction class which will interact with the host
        with SSHClientInteraction(client, timeout=10, display=True) as interact:
            #### interact.expect(PROMPT) 

            # Run the first command and capture the cleaned output, if you want
            # the output without cleaning, simply grab current_output instead.
            interact.send('uname -a')
            interact.expect(PROMPT)
            cmd_output_uname = interact.current_output_clean

            # Now let's do the same for the ls command but also set a timeout for
            # this specific expect (overriding the default timeout)
            interact.send('ls -l /')
            interact.expect(PROMPT, timeout=5)
            cmd_output_ls = interact.current_output_clean

        # Print the output of each command
        print '-'*79
        print 'Cleaned Command Output'
        print '-'*79
        print 'uname -a output:'
        print cmd_output_uname
        print 'ls -l / output:'
        print cmd_output_ls

    except Exception:
        traceback.print_exc()
    finally:
        try:
            client.close()
        except:
            pass

if __name__ == '__main__':
    main()

result

Last login: Fri Dec  1 09:30:38 2017 from 172.30.3.29
uname -a
[root@template ~]# uname -a
Linux template 2.6.32-642.15.1.el6.x86_64 #1 SMP Fri Feb 24 14:31:22 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
[root@template ~]# Traceback (most recent call last):
  File "D:/cookbook/ssh/test_paramiko_expect.py", line 45, in main
    interact.expect(PROMPT)
  File "D:\Python27\lib\site-packages\paramiko_expect.py", line 144, in expect
    current_buffer = self.channel.recv(self.buffer_size)
  File "D:\Python27\lib\site-packages\paramiko\channel.py", line 685, in recv
    raise socket.timeout()
timeout
nanacoding commented 6 years ago

I change PROMPT to PROMPT = re.escape('[root@template ~]# ') it works. Sorry, It is my bug.

fruch commented 6 years ago

no worries, regexs are always fun ;)