在webssh中使用tail -f xxx.log命令的时候,因为获取的二进制流中有中文字符的情况
class SSH:
def __init__(self, websocker, message):
self.websocker = websocker
self.message = message
self.errormessage = ''
self.unicodeerrordata = ''
self.newunicodedata = ''
self.data = ''
def connect(self, host, user, password=None, pkey=None, port=22, timeout=120,
term='xterm', pty_width=80, pty_height=24):
try:
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
if password:
ssh_client.connect(username=user, password=password, hostname=host, port=port, timeout=timeout)
else:
ssh_client.connect(username=user, hostname=host, port=port, timeout=timeout)
transport = ssh_client.get_transport()
self.channel = transport.open_session()
self.channel.get_pty(term=term, width=pty_width, height=pty_height)
self.channel.invoke_shell()
for i in range(2):
recv = self.channel.recv(1024).decode('utf-8')
self.message['status'] = 0
self.message['message'] = recv
message = json.dumps(self.message)
self.websocker.send(message)
except socket.timeout as e:
self.errormessage = e
self.message['status'] = 1
self.message['message'] = 'ssh 连接超时'
message = json.dumps(self.message)
logging.info('connet server timeout')
self.websocker.send(message)
self.websocker.close()
except Exception as e:
self.errormessage = e
self.message['status'] = 1
self.message['message'] = str(e)
message = json.dumps(self.message)
logging.info('connet server custom')
self.websocker.send(message)
self.websocker.close()
def resize_pty(self, cols, rows):
self.channel.resize_pty(width=cols, height=rows)
def django_to_ssh(self, data):
try:
if ' ' in data:
print('回车')
if data == '^C':
print(str(data))
self.close()
self.channel.send(data)
return
except Exception as err:
print(err)
self.errormessage = err
self.close()
def websocket_to_django(self,httpobj):
try:
while True:
# self.get_recv_data(self.channel)
data_bytes = self.channel.recv(1024)
data_list = data_bytes.split(b' ')
logging.info('data_len: {}'.format(len(data_list)))
if self.data:
data_list[0] = self.data + data_list[0]
data = ' '.join([i.decode('utf-8') for i in data_list[:-1]])
else:
data = ' '.join([i.decode('utf-8') for i in data_list[:-1]])
self.data = data_list[-1]
logging.info('data: {}'.format(data))
if not len(data):
data = ''
self.message['status'] = 0
self.message['message'] = data
message = json.dumps(self.message)
self.websocker.send(message)
try:
if httpobj:
httpobj.savecommend(str(data))
except Exception as e:
print(e)
self.errormessage = e
except Exception as e:
self.errormessage = e
self.close()
def close(self):
self.message['status'] = 1
logging.info('unicodeerrordata: {}'.format(self.unicodeerrordata))
logging.info('errormessage: {}'.format(self.errormessage))
logging.info('newunicodedata: {}'.format(self.newunicodedata))
self.message['message'] = '关闭连接'
message = json.dumps(self.message)
self.websocker.send(message)
self.channel.close()
self.websocker.close()
def shell(self, data, httpobj=None):
Thread(target=self.django_to_ssh, args=(data,)).start()
Thread(target=self.websocket_to_django, args=(httpobj,)).start()
在这里每次都会获取1024个字符,因为中文的二进制字符是这样的 'xE5x85x84' ,3个x85之类的字符才能被decode('utf-8')解析,
因为在获取1024个字节的情况下会把中文组成的12个字节拆散,当用decode('utf-8')解析的时候就会出现错误,造成webssh连接关
闭的情况。
在上面的代码中我做了一个对获取的1024个字节的拆解,用' '分割,把最后一个换行符分出来的字符串和下一次获取的字符串做拼接,
这样就能保证中文的12个字符是完整的,也就避免了解析报错