我编写了以下python模块来处理程序中的ssh连接:
#!/usr/bin/env python
from vxpty import VX_PTY
class SSHError(Exception):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return repr(self.msg)
class SSHShell:
def __init__(self, host, port, user, password):
self.host = host
self.port = port
self.user = user
self.password = password
self.authenticated = False
def authenticate(self):
self.tty = VX_PTY(['/usr/bin/ssh', 'ssh', '-p'+str(self.port), self.user+'@'+self.host])
resp = self.tty.read()
if "authenticity of host" in resp:
self.tty.println('yes')
while 1:
resp = self.tty.read()
if "added" in resp:
break
resp = self.tty.read()
if "assword:" in resp:
self.tty.println(self.password)
tmp_resp = self.tty.read()
tmp_resp += self.tty.read()
if "denied" in tmp_resp or "assword:" in tmp_resp:
raise(SSHError("Authentication failed"))
else:
self.authenticated = True
self.tty.println("PS1=''")
return self.authenticated
def execute(self, os_cmd):
self.tty.println(os_cmd)
resp_buf = self.tty.read().replace(os_cmd+'\r\n', '')
return resp_buf
它使用了我之前编写的pty模块:
^{pr2}$但是,每当我调用execute()
方法时,我都会从第一行读取输出:
>>> import SSH;shell=SSH.SSHShell('localhost',22,'735tesla','notmypassword');shell.authenticate()
True
>>> shell.execute('whoami')
"\x1b[?1034hLaptop:~ 735Tesla$ PS1=''\r\n"
>>>
第二次调用read()
时,我得到了输出:
>>> shell.tty.read()
'whoami\r\n735Tesla\r\n'
>>>
从输出中删除whoami\r\n
不是问题,但是有没有方法可以清除输出,这样我就不必在第一个命令中调用read两次了?在
我认为你的问题比你意识到的更深。幸运的是,它比你想象的要容易解决。在
您似乎希望
os.read
在一次调用中返回shell必须发送给您的全部内容。这不是你可以要求的。取决于几个因素,包括但不限于shell的实现、网络带宽和延迟,以及pty(您和远程主机的)的行为,每次调用read
时返回的数据量可以是所有数据量,也可以是一个字符。在如果您只想接收命令的输出,就应该用唯一的标记将其括起来,不要担心会弄乱PS1。我的意思是,您需要在命令执行之前使shell输出成为唯一的字符串,在命令执行之后再输出另一个字符串。然后,
tty.read
方法应该返回它在这两个标记字符串之间找到的所有文本。使shell输出这些唯一字符串的最简单方法就是使用echo命令。在对于多行命令,必须将命令包装在shell函数中,并在执行函数之前和之后回显标记。在
一个简单的实现如下:
相关问题 更多 >
编程相关推荐