Paramiko互动外壳冻结在recv(9999)

时间:2017-07-25 03:47:40

标签: shell paramiko

我有一个paramiko交互式shell,我试图用来登录远程linux主机:

class SSH_wrapper(object):
"""
A SSH Client powered by Paramiko.
"""
def __init__(self, hostname, port=22, username=None, password=None,
             key=None, key_passphrase=None, encoding='UTF-8', timeout=300, prompts = None):
    self.hostname = hostname
    self.port = port
    self.username = username
    self.password = password
    self.passphrase = key_passphrase
    self.key = key
    self.timeout = timeout
    self.encoding = encoding
    self.prompts = prompts
    self.client = paramiko.SSHClient()
    self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

def connect(self):
    conninfo = {'hostname': self.hostname,
                'port': self.port,
                'username': self.username,
                'allow_agent': False,
                'look_for_keys': False}

    if self.password:
        conninfo['password'] = self.password
    elif self.key:
        conninfo['key_filename'] = self.key
        conninfo['password'] = self.passphrase
    else:
        conninfo['allow_agent'] = True
        conninfo['look_for_keys'] = True

    if self.timeout:
        conninfo['timeout'] = self.timeout
    else:
        conninfo['timeout'] = 180

    try:
        self.client.connect(**conninfo)
    except paramiko.ssh_exception.AuthenticationException:
        print("Authentication failed for user name \"" + str(self.username) + "\".")
        return False
    except paramiko.ssh_exception.SSHException:
        print("SSHException found.  Could not connect to \"" + str(self.hostname) + "\".")
        return False
    except:
        e = sys.exc_info()[0]
        print("Could not connect to host \"" + str(self.hostname) + "\".  Found exception: " + str(e) + ".")
        return False
    banner = self.client._transport.get_banner()
    #print(str(banner, 'utf-8'))
    return True

def open_shell_session(self, prompts=None, timeout=None):
    if (timeout != None) and (type(timeout) is int):
        open_timeout = timeout
    else:
        open_timeout = self.timeout

    no_prompts = 0
    if (prompts != None and self.prompts == None):
        no_prompts = 1
    elif (prompts != None and self.prompts != None):
        prompts = self.prompts

    channel_data = b""
    try:
        self.shell = self.client.invoke_shell(term='vt100')
    except paramiko.ssh_exception.SSHException:
        print("SSHException found.  Could not open SSH shell to \"" + str(self.hostname) + "\".")
        return [False, ""]
    except:
        e = sys.exc_info()[0]
        print("Could not open SSH shell to \"" + str(self.hostname) + "\".  Found exception: " + str(e) + ".")
        return [False, ""]

    start_time = time.time()

    # when testing be sure to test with session where prompt is not recognized.
    while True and (time.time() - start_time <= open_timeout):
        print("loop " + str(time.time() - start_time))
        self.shell.settimeout(5000)

        try:
            channel_data += self.shell.recv(9999)
            print(str(channel_data, 'utf-8'))
        except:
            e = sys.exc_info()[0]
            print("Found exception: " + str(e) + ".")
        if self.shell.exit_status_ready() == True:
            print("exit status received.")

        print("received channel data.")
        if no_prompts == 1:
            time.sleep(4)
            break
        elif (prompts != None) and (re.search("|".join(prompts), str(channel_data, 'utf-8'))):
            break

        print("end of while loop.")
    else:
        print("Time out connecting to host \"" + str(self.hostname) + "\".")
        return [False, str(channel_data, self.encoding)]

    # return [status, banner]
    print("exiting")
    return [True, str(channel_data, self.encoding)]

我不确定为什么但是当我尝试登录主机时,它会提示我更改密码&#34; open_shell_session()&#34;冻结在&#34; channel_data + = self.shell.recv(9999)&#34;。

当我尝试打开交互式shell时,以下是linux shell的示例提示/标题:

|________________________________________________________________|

WARNING: Your password has expired. You must change your password now and login again! 
Changing password for user xxxx. 
Changing password for xxxx. 
(current) UNIX password:

关于问题的任何建议(recv(9999)仍然开放)?如何处理?

1 个答案:

答案 0 :(得分:1)

刚做了一个测试,它对我有用(我使用的是Python 2.7):

>>> import socket, paramiko
>>> ssh = paramiko.SSHClient()
>>> ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy() )
>>> ssh.connect('127.0.0.1', username = 'bar', password = 'aaa')
>>> chan = ssh.invoke_shell()
>>> chan.recv_ready()
True
>>> v = chan.recv(9999)
>>> print v
[..snipped..]
WARNING: Your password has expired.
You must change your password now and login again!
Changing password for bar.
(current) UNIX password:
>>>