1. 程式人生 > 實用技巧 >造成webssh突然close的中文字元編碼問題的解決

造成webssh突然close的中文字元編碼問題的解決

在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 '\n' 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'\n')
logging.info('data_len: {}'.format(len(data_list)))
if self.data:
data_list[0] = self.data + data_list[0]
data = '\n'.join([i.decode('utf-8') for i in data_list[:-1]])
else:
data = '\n'.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個字元,因為中文的二進位制字元是這樣的 '\xE5\x85\x84' ,3個\x85之類的字元才能被decode('utf-8')解析,

因為在獲取1024個位元組的情況下會把中文組成的12個位元組拆散,當用decode('utf-8')解析的時候就會出現錯誤,造成webssh連線關

閉的情況。

在上面的程式碼中我做了一個對獲取的1024個位元組的拆解,用'\n'分割,把最後一個換行符分出來的字串和下一次獲取的字串做拼接,

這樣就能保證中文的12個字元是完整的,也就避免瞭解析報錯