2017-07-25 16 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