def run(self): # fix the first login 1 bug first_flag = True command = list() if self.elementid: logobj = Log.objects.get(channel=self.elementid) else: logobj = Log.objects.get(channel=self.message.reply_channel.name) while (not self._stop_event.is_set()): text = self.queue.get_message() if text: # deserialize data if isinstance(text['data'], (str, basestring, unicode)): try: data = ast.literal_eval(text['data']) except Exception, e: data = text['data'] else: data = text['data'] if isinstance(data, (list, tuple)): if data[0] == 'close': logger.debug('close threading') self.chan.close() self.stop() elif data[0] == 'set_size': self.chan.resize_pty(width=data[3], height=data[4]) break elif data[0] in ['stdin', 'stdout']: if '\r' not in str(data[1]): command.append(data[1]) else: # fix command record duplicate if len(data) >= 3 and data[2] == 'command': CommandLog.objects.create( log=logobj, command=data[1].strip('r')[0:255]) self.chan.send(data[1]) elif isinstance(data, (int, long)): if data == 1 and first_flag: first_flag = False else: self.chan.send(str(data)) else: try: # get user command and block user action in the future if '\r' not in str(data) or '\n' not in str(data): command.append(str(data)) else: record_command = CommandDeal().deal_command( ''.join(command)) if len(record_command) != 0: logger.debug( 'command input {0}'.format(record_command)) command = list() # vi bug need to be fixed self.chan.send(str(data)) except socket.error: logger.error('close threading error') self.stop()
def run(self): #fix the first login 1 bug first_flag = True command = list() while (not self._stop_event.is_set()): text = self.queue.get_message() if text: #deserialize data if isinstance(text['data'], (str, basestring, unicode)): try: data = ast.literal_eval(text['data']) except Exception, e: data = text['data'] else: data = text['data'] if isinstance(data, (list, tuple)): if data[0] == 'close': print('close threading') self.chan.close() self.stop() elif data[0] == 'set_size': self.chan.resize_pty(width=data[3], height=data[4]) break elif data[0] in ['stdin', 'stdout']: self.chan.send(data[1]) elif isinstance(data, (int, long)): if data == 1 and first_flag: first_flag = False else: self.chan.send(str(data)) else: try: #get user command and block user action in the future if '\r' not in str(data): command.append(str(data)) else: record_command = CommandDeal().deal_command( ''.join(command)) if len(record_command) != 0: print('command input', record_command) command = list() #vi bug need to be fixed self.chan.send(str(data)) except socket.error: print('close threading error') self.stop()
def posix_shell(chan, channel, channelid): stdout = list() begin_time = time.time() last_write_time = {'last_activity_time': begin_time} command = list() logobj = Log.objects.get(log=channelid) vim_flag = False vim_data = '' try: directory_date_time = timezone.now() log_name = os.path.join( '{0}-{1}-{2}'.format(directory_date_time.year, directory_date_time.month, directory_date_time.day), '{0}'.format(channelid)) from webterminal.asgi import channel_layer # terminate ssh session control redis_instance = get_redis_instance() redis_sub = redis_instance.pubsub() redis_sub.subscribe(logobj.channel) while True: text = redis_sub.get_message() if text: try: if isinstance(text['data'], bytes): text['data'] = smart_unicode(text['data']) data = json.loads(text['data']) except: data = [] if len(data) >= 1 and str(data[0]) == 'close': if not channel.closed: channel.close() r, w, x = select.select([channel], [], []) if channel in r: data = channel.recv(1024 * 24) if len(data) == 0: if not channel.closed: channel.send('\r\n*** EOF\r\n') break if data == "exit\r\n" or data == "logout\r\n" or data == 'logout': channel.close() now = time.time() delay = now - last_write_time['last_activity_time'] last_write_time['last_activity_time'] = now if vim_flag: vim_data += data if '\r' not in smart_unicode(data): command.append(smart_unicode(data)) else: command_result = CommandDeal().deal_command( ''.join(command)) if len(command_result) != 0: # vim command record patch if command_result.strip().startswith( 'vi') or command_result.strip().startswith( 'fg'): CommandLog.objects.create( log=logobj, command=command_result[0:255]) vim_flag = True else: if vim_flag: if re.compile('\[.*@.*\][\$#]').search( vim_data): vim_flag = False vim_data = '' else: CommandLog.objects.create( log=logobj, command=command_result[0:255]) command = list() if isinstance(data, unicode): stdout.append([delay, data]) else: stdout.append([ delay, codecs.getincrementaldecoder('UTF-8')( 'replace').decode(data) ]) channel_layer.send_group( smart_unicode('monitor-{0}'.format(channelid)), {'text': json.dumps(['stdout', smart_unicode(data)])}) if not chan.closed: chan.send(data) else: print('else') finally: attrs = { "version": 1, "width": 180, "height": 40, "duration": round(time.time() - begin_time, 6), "command": os.environ.get('SHELL', None), 'title': None, "env": { "TERM": os.environ.get('TERM'), "SHELL": os.environ.get('SHELL', 'sh') }, 'stdout': list(map(lambda frame: [round(frame[0], 6), frame[1]], stdout)) } mkdir_p('/'.join(os.path.join(MEDIA_ROOT, log_name).rsplit('/')[0:-1])) with open(os.path.join(MEDIA_ROOT, log_name), "a") as f: f.write( json.dumps(attrs, ensure_ascii=True, cls=CustomeFloatEncoder, indent=2)) logobj.is_finished = True logobj.end_time = timezone.now() logobj.save() chan.close() channel.close()
def posix_shell(chan, channel, log_name=None, width=90, height=40, elementid=None): from webterminal.asgi import channel_layer stdout = list() begin_time = time.time() last_write_time = {'last_activity_time': begin_time} command = list() if elementid: logobj = Log.objects.get(channel=elementid) else: logobj = Log.objects.get(channel=channel) vim_flag = False vim_data = '' try: chan.settimeout(0.0) while True: try: x = u(chan.recv(1024)) if len(x) == 0: if elementid: channel_layer.send( channel, { 'text': json.dumps([ 'disconnect', smart_unicode('\r\n*** EOF\r\n'), elementid.rsplit('_')[0] ]) }) else: channel_layer.send( channel, { 'text': json.dumps([ 'disconnect', smart_unicode('\r\n*** EOF\r\n') ]) }) break now = time.time() delay = now - last_write_time['last_activity_time'] last_write_time['last_activity_time'] = now if x == "exit\r\n" or x == "logout\r\n" or x == 'logout': chan.close() else: if vim_flag: vim_data += x logger.debug('raw data {0}'.format(command)) if '\r\n' not in x: command.append(x) else: command = CommandDeal().deal_command(''.join(command)) if len(command) != 0: #vim command record patch logger.debug('command {0}'.format(command)) if command.strip().startswith( 'vi') or command.strip().startswith('fg'): CommandLog.objects.create(log=logobj, command=command) vim_flag = True else: if vim_flag: if re.compile('\[.*@.*\][\$#]').search( vim_data): vim_flag = False vim_data = '' else: CommandLog.objects.create(log=logobj, command=command) command = list() if isinstance(x, unicode): stdout.append([delay, x]) else: stdout.append([ delay, codecs.getincrementaldecoder('UTF-8')( 'replace').decode(x) ]) if isinstance(x, unicode): if elementid: channel_layer.send( channel, { 'text': json.dumps( ['stdout', x, elementid.rsplit('_')[0]]) }) else: channel_layer.send(channel, {'text': json.dumps(['stdout', x])}) else: if elementid: channel_layer.send( channel, { 'text': json.dumps([ 'stdout', smart_unicode(x), elementid.rsplit('_')[0] ]) }) else: channel_layer.send( channel, {'text': json.dumps(['stdout', smart_unicode(x)])}) #send message to monitor group if log_name: channel_layer.send_group( u'monitor-{0}'.format(log_name.rsplit('/')[1]), {'text': json.dumps(['stdout', smart_unicode(x)])}) except socket.timeout: pass except Exception, e: logger.error(traceback.print_exc()) if elementid: channel_layer.send( channel, { 'text': json.dumps([ 'stdout', 'A bug find,You can report it to me' + smart_unicode(e), elementid.rsplit('_')[0] ]) }) else: channel_layer.send( channel, { 'text': json.dumps([ 'stdout', 'A bug find,You can report it to me' + smart_unicode(e) ]) }) finally: attrs = { "version": 1, "width": width, #int(subprocess.check_output(['tput', 'cols'])), "height": height, #int(subprocess.check_output(['tput', 'lines'])), "duration": round(time.time() - begin_time, 6), "command": os.environ.get('SHELL', None), 'title': None, "env": { "TERM": os.environ.get('TERM'), "SHELL": os.environ.get('SHELL', 'sh') }, 'stdout': list(map(lambda frame: [round(frame[0], 6), frame[1]], stdout)) } mkdir_p('/'.join(os.path.join(MEDIA_ROOT, log_name).rsplit('/')[0:-1])) with open(os.path.join(MEDIA_ROOT, log_name), "a") as f: f.write( json.dumps(attrs, ensure_ascii=True, cls=CustomeFloatEncoder, indent=2)) if elementid: audit_log = Log.objects.get(channel=elementid, log=log_name.rsplit('/')[-1]) else: audit_log = Log.objects.get(channel=channel, log=log_name.rsplit('/')[-1]) audit_log.is_finished = True audit_log.end_time = timezone.now() audit_log.save() #hand ssh terminal exit queue = get_redis_instance() redis_channel = queue.pubsub() queue.publish(channel, json.dumps(['close']))
def run(self): # fix the first login 1 bug first_flag = True command = list() if self.elementid: logobj = Log.objects.get(channel=self.elementid) else: logobj = Log.objects.get(channel=self.message.reply_channel.name) while (not self._stop_event.is_set()): text = self.queue.get_message() if text: # deserialize data if isinstance(text['data'], (str, basestring, unicode, bytes)): if isinstance(text['data'], bytes): try: data = ast.literal_eval( text['data'].decode('utf8')) except Exception as e: data = text['data'] else: try: data = ast.literal_eval(text['data']) except Exception as e: data = text['data'] else: data = text['data'] if isinstance(data, (list, tuple)): if data[0] == 'close' or data[0] == "'close'": logger.debug('close threading') try: self.chan.send('<<<close>>>') # close flag except OSError: pass time.sleep(3) self.chan.transport.close() self.chan.close() self.stop() elif data[0] == 'set_size': try: self.chan.resize_pty(width=data[3], height=data[4], width_pixels=data[1], height_pixels=data[2]) except (TypeError, struct.error, paramiko.SSHException): pass elif data[0] in ['stdin', 'stdout']: if '\r' not in str(data[1]): command.append(data[1]) else: # fix command record duplicate if len(data) >= 3 and data[2] == 'command': CommandLog.objects.create( log=logobj, command=data[1].strip('r')[0:255]) self.chan.send(data[1]) elif isinstance(data, (int, long)): if data == 1 and first_flag: first_flag = False else: if isinstance(data, bytes): self.chan.send(data) else: self.chan.send(str(data)) else: try: # get user command and block user action in the future if '\r' not in str(data) or '\n' not in str(data): command.append(str(data)) else: record_command = CommandDeal().deal_command( ''.join(command)) if len(record_command) != 0: logger.debug( 'command input {0}'.format(record_command)) command = list() # vi bug need to be fixed if isinstance(data, bytes): self.chan.send(data) else: self.chan.send(str(data)) except socket.error: logger.error('close threading error') self.stop() # avoid cpu usage always 100% time.sleep(0.001)