2017-07-25 18 views
0

我有我尝试使用登录到远程Linux主机上的paramiko交互的shell:的paramiko交互shell冻结在的recv(9999)

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)] 

我不知道为什么,但是当我尝试登录到它提示我更改密码的主机“open_shell_session()”在“channel_data + = self.shell.recv(9999)”处冻结。

这里是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)仍处于打开状态)?如何处理它?

+0

您的密码已过期。你可以在'invoke_shell()'之前改变你的密码。 – pynexj

+0

是的,我明白了:)。但我想让我的脚本执行该操作。 – ozn

+0

* *中的* *我想让我的脚本执行那个*? – pynexj

回答

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: 
>>> 
+0

谢谢。我能够利用recv_ready()来解决我的问题。 – ozn