我有一个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)仍然开放)?如何处理?
答案 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:
>>>