def run(self): """ Listen to invoked script for any bugs to report """ scriptName = self.parsingCommandLineArguments()['userScript'] p = subprocess.Popen([scriptName], stderr=subprocess.PIPE, stdout=subprocess.PIPE, stdin=subprocess.PIPE, shell=True) sel = selectors2.DefaultSelector() sel.register(p.stderr, selectors2.EVENT_READ) while True: for key, _ in sel.select(): sleep(1.5) traceback = key.fileobj.read1().decode() if not traceback: exit() # Visual / Demo purposes print(traceback, end="", file=sys.stderr) if str(traceback).find("ModuleNotFoundError:") != -1: raise Exception(f'{scriptName}, module is not found!') elif str(traceback).find("No such file or directory") != -1: raise Exception(f'{scriptName} script is not found!') # if bug encountered DOES NOT appear in black list data, you CAN send bug to server if not self.filterBugReport.blacklist_check(str(traceback)): # send bug to server respondCode = self.server.sendToServer(traceback) if respondCode.status_code != 200: logging.error( "Unable to report bug to server, response code: " + str(respondCode.status_code))
def bridge(self): # 桥接 客户终端 和 代理服务终端 交互 transport_keepalive(self.chan_ser.transport) sel = selectors.DefaultSelector() # Linux epol sel.register(self.chan_cli, selectors.EVENT_READ) sel.register(self.chan_ser, selectors.EVENT_READ) while self.chan_ser and self.chan_cli and not (self.chan_ser.closed or self.chan_cli.closed): events = sel.select(timeout=60) # import ipdb; ipdb.set_trace() for key, n in events: if key.fileobj == self.chan_ser: try: x = self.chan_ser.recv(1024) if len(x) == 0: self.chan_cli.send("\r\n服务端已断开连接....\r\n") return self.chan_cli.send(x) except socket.timeout: pass if key.fileobj == self.chan_cli: try: x = self.chan_cli.recv(1024) if len(x) == 0: print("\r\n客户端断开了连接....\r\n") return self.chan_ser.send(x) except socket.timeout: pass except socket.error: break
def begin(self): print "Attempt to listen for incoming on", self.addr, "at port", self.port while True: try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) incoming = (self.addr, self.port) sock.bind(incoming) except socket.error as e: print "Socket listener connection failed", e print "Retrying" else: break finally: time.sleep(3) sock.listen(1) (connection, address) = sock.accept() sock.shutdown(socket.SHUT_RDWR) sock.close() # Close the initial socket. print "Listening to new socket on", address[0], "at port", address[1] self.sock = connection self.sock.setblocking(False) events = selectors.EVENT_READ self.selector = selectors.DefaultSelector() self.selector.register(self.sock, events, data=self)
def __init__(self): self.sock = self.daemon = self.locationStr = None if selectors is None: raise RuntimeError("This Python installation doesn't have the 'selectors2' or 'selectors34' module installed, " + "which is required to use Pyro's multiplex server. Install it, or use the threadpool server instead.") self.selector = selectors.DefaultSelector() self.shutting_down = False
def __init__(self, fchan): self.fchan = fchan self.bchan = None self.is_first_input = True self.in_input_state = False self.ENTER_CHAR = ('\r', '\n', '\r\n') self.sel = selectors.DefaultSelector()
def __init__(self, config_path=os.path.join(current_dir, os.pardir, "config", "client.ini")): """ Initializtion ```python client = Client(config_path) ``` Args: config_path (string, optional): Path to the file with configuration. There also should be config specification file at `<config_path>\config\configspec_client.ini`. Defaults to `<current_dir>\os.pardir\config\client.ini`. """ self.selector = selectors.DefaultSelector() self.client_socket = None self.server_connection = messaging.ConnectionManager() self.connected = False self.client_id = None # Init configs self.config = ConfigManager() self.config_path = config_path global active_client active_client = self
def __init__(self, host, port): self.host = host self.port = port self.logger = logging.getLogger(self.__class__.__name__) self.send_queue = queue.Queue() self.mysel = selectors.DefaultSelector() self.keep_running = True signal(SIGINT, self._handle_sigint)
def _create_all(self): self._selector = selectors.DefaultSelector() self._req_queue = queue.Queue() self._sync_req_timeout = 12 self._thread = None now = datetime.now() self._last_activate_time = now self._last_check_req_time = now self._r_sock, self._w_sock = make_ctrl_socks() self._selector.register(self._r_sock, selectors.EVENT_READ)
def connect(self, addr, port): server_addr = (str(addr), int(port)) self.addr = server_addr print "starting connection to", server_addr sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setblocking(False) sock.connect_ex(server_addr) self.sock = sock events = selectors.EVENT_READ | selectors.EVENT_WRITE self.selector = selectors.DefaultSelector() self.selector.register(sock, events, data=self)
def bridge(self): # 桥接 客户终端 和 代理服务终端 交互 transport_keepalive(self.chan_ser.transport) sel = selectors.DefaultSelector() # Linux epol sel.register(self.chan_cli, selectors.EVENT_READ) sel.register(self.chan_ser, selectors.EVENT_READ) sshlog = proxys.newlog(self, self.hostid, self.http_user) # 终端日志 stdouts = [] # 录像记录 begin_time = last_activity_time = time.time() while self.chan_ser and self.chan_cli and not (self.chan_ser.closed or self.chan_cli.closed): events = sel.select(timeout=60) # import ipdb; ipdb.set_trace() for key, n in events: if key.fileobj == self.chan_ser: try: x = self.chan_ser.recv(1024) if len(x) == 0: self.chan_cli.send("\r\n服务端已断开连接....\r\n") time.sleep(1) break else: self.chan_cli.send(x) # 记录操作录像 now = time.time() delay = round(now - last_activity_time, 6) last_activity_time = now # print[delay, x], 999 stdouts.append([delay, x]) except socket.timeout: pass if key.fileobj == self.chan_cli: try: x = self.chan_cli.recv(1024) if len(x) == 0: print("\r\n客户端断开了连接....\r\n") time.sleep(1) break else: self.chan_ser.send(x) except socket.timeout: pass except socket.error: break # self.close() # sshlog.save() times = round(time.time() - begin_time, 6) # 录像总时长 # import ipdb; ipdb.set_trace() savelog(sshlog, times, stdouts, stdins=[])
def __init__(self): self._selector = selectors.DefaultSelector() self._is_polling = False self._next_conn_id = 1 self._lock = threading.RLock() self._sync_req_timeout = 10 self._thread = None self._use_count = 0 self._owner_pid = 0 self._connecting_sock_dict = {} # sock -> conn_time now = datetime.now() self._last_activate_time = now self._last_check_req_time = now
def __init__(self, config_path="config/client.ini"): self.selector = selectors.DefaultSelector() self.client_socket = None self.server_connection = messaging.ConnectionManager() self.connected = False self.client_id = None # Init configs self.config = ConfigManager() self.config_path = config_path global active_client active_client = self
def __init__(self, server_addr): """IoT client with persistent connection Each message separated by b'\n' """ sock = socket(AF_INET, SOCK_STREAM) sock.connect(server_addr) # connect to server process rfile = sock.makefile('rb') # file-like obj sel = selectors.DefaultSelector() sel.register(sock, selectors.EVENT_READ) self.sock = sock self.rfile = rfile self.sel = sel self.requests = {} # messages sent but not yet received their responses self.time_to_expire = None
def __init__(self): self.selector = selectors.DefaultSelector() self.server = socket.socket() self.server.setblocking(False) # 存放文件路径 self.file_path_dict = {} # 存放文件总大小 self.file_size_dict = {} # 存放get文件对象 self.get_fd_dict = {} # 存放put文件对象 self.put_fd_dict = {} # 存放put收到文件大小 self.put_file_size_dict = {} # 存放get发送文件大小 self.get_file_size_dict = {} # 存放用户数据 self.user_data = {}
def __init__(self, config_path="client_config.ini"): self.selector = selectors.DefaultSelector() self.client_socket = None self.server_connection = messaging.ConnectionManager("pi") self.server_host = None self.server_port = None self.broadcast_port = None self.connected = False self.client_id = None # Init configs self.config_path = config_path self.config = ConfigParser.ConfigParser() self.load_config() global active_client active_client = self
def bridge(self): # 桥接 客户终端 和 代理服务终端 交互 # transport_keepalive(self.chan_ser.transport) sel = selectors.DefaultSelector() # Linux epol sel.register(self.chan_cli, selectors.EVENT_READ) sel.register(self.chan_ser, selectors.EVENT_READ) while self.chan_ser and self.chan_cli and not (self.chan_ser.closed or self.chan_cli.closed): events = sel.select(timeout=60) for key, n in events: if key.fileobj == self.chan_ser: try: recv_message = self.chan_ser.recv(1024) if len(recv_message) == 0: self.chan_cli.send("\r\n服务端已断开连接....\r\n") time.sleep(1) break else: try: # 发送数据给查看会话的 websocket 组 message = dict() message['status'] = 0 message['message'] = recv_message.decode('utf-8') channel_layer = get_channel_layer() async_to_sync(channel_layer.group_send)(self.group, { "type": "chat.message", "text": message, }) except: pass self.chan_cli.send(recv_message) # 记录操作录像 try: """ 防止 sz rz 传输文件时的报错 """ delay = round(time.time() - self.start_time, 6) self.res_asciinema.append(json.dumps([delay, 'o', recv_message.decode('utf-8')])) # 250条结果或者指定秒数就保存一次,这个任务可以优化为使用 celery if len(self.res_asciinema) > 250 or int(time.time() - self.last_save_time) > 30: tmp = list(self.res_asciinema) self.res_asciinema = [] self.last_save_time = time.time() with open(settings.TERMINAL_LOGS + '/' + self.res_file, 'a+') as f: for line in tmp: f.write('{}\n'.format(line)) except BaseException: pass except socket.timeout: pass if key.fileobj == self.chan_cli: try: send_message = self.chan_cli.recv(1024) if len(send_message) == 0: print("\r\n客户端断开了连接....\r\n") time.sleep(1) break else: self.chan_ser.send(send_message) except socket.timeout: pass except socket.error: break
def make_selector(self): s = selectors2.DefaultSelector() self.addCleanup(s.close) return s
def __init__(self, port): self.port = port self.selector = selectors.DefaultSelector() self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.start = False
class clientListener: identDict = {} listenerSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) mainSelector = selectors.DefaultSelector() def __init__(self): self.actClient = custClient.pyClient() clientListener.listenerSocket.bind((HOST, PORT)) clientListener.listenerSocket.listen(6) clientListener.listenerSocket.setblocking(False) clientListener.mainSelector.register(clientListener.listenerSocket, selectors.EVENT_READ, data=None) while True: events = clientListener.mainSelector.select(timeout=None) for key, mask in events: if not key.data: self.accept(key.fileobj) else: if not key.data.handled: self.answer(key, mask) clientListener.mainSelector.unregister(key.fileobj) key.fileobj.close() print("closed") def accept(self, sock): conn, addr = sock.accept() print("verbindung akzeptiert von: ") conn.setblocking(False) print(addr) d = reqData(addr, "") events = selectors.EVENT_READ | selectors.EVENT_WRITE clientListener.mainSelector.register(conn, events, data=d) def answer(self, key, mask): sock = key.fileobj data = key.data if mask & selectors.EVENT_READ: piRequest = sock.recv(1024).decode("utf-8") if not data.handled: data.piReq = piRequest data.handled = True else: clientListener.mainSelector.unregister(sock) print("closing socket ...") sock.close() if mask & selectors.EVENT_WRITE: handle = self.actClient.handle(data.piReq) if handle: answer = handle if isinstance(answer, str): msgLen = "{:04d}".format(len(answer)) finmsg = str(msgLen) + answer sock.sendall(finmsg.encode("utf-8")) else: listLen = len(answer) for msg in answer: listLen = listLen - 1 msgLen = "{:04d}".format( int(min(listLen, 1) * 1000 + len(msg))) finmsg = str(msgLen) + msg sock.sendall(finmsg.encode("utf-8"))
def bridge(self): # 桥接 客户终端 和 代理服务终端 交互 # transport_keepalive(self.chan_ser.transport) sel = selectors.DefaultSelector() # Linux epol sel.register(self.chan_cli, selectors.EVENT_READ) sel.register(self.chan_ser, selectors.EVENT_READ) try: while self.chan_ser and self.chan_cli and not (self.chan_ser.closed or self.chan_cli.closed): events = sel.select(timeout=terminal_exipry_time) # 指定时间无数据输入或者无数据返回则断开连接 if not events: raise socket.timeout for key, n in events: if key.fileobj == self.chan_ser: try: recv_message = self.chan_ser.recv(1024) if self.zmodem: if b'**\x18B0800000000022d\r\x8a' in recv_message: self.zmodem = False delay = round(time.time() - self.start_time, 6) self.res_asciinema.append(json.dumps([delay, 'o', '\r\n'])) # logger.info("zmodem end") self.chan_cli.send(recv_message) continue else: if b'rz\r**\x18B00000000000000\r\x8a' in recv_message or b'rz waiting to receive.**\x18B0100000023be50\r\x8a' in recv_message: self.zmodem = True # logger.info("zmodem start") self.chan_cli.send(recv_message) continue # logger.info(recv_message) if len(recv_message) == 0: self.chan_cli.send("\r\n\033[31m服务端已断开连接....\033[0m\r\n") time.sleep(1) break else: try: # 发送数据给查看会话的 websocket 组 message = dict() message['status'] = 0 message['message'] = recv_message.decode('utf-8') channel_layer = get_channel_layer() async_to_sync(channel_layer.group_send)(self.group, { "type": "chat.message", "text": message, }) except UnicodeDecodeError: try: recv_message += self.chan_ser.recv(1) message = dict() message['status'] = 0 message['message'] = recv_message.decode('utf-8') channel_layer = get_channel_layer() async_to_sync(channel_layer.group_send)(self.group, { "type": "chat.message", "text": message, }) except UnicodeDecodeError: try: recv_message += self.chan_ser.recv(1) message = dict() message['status'] = 0 message['message'] = recv_message.decode('utf-8') channel_layer = get_channel_layer() async_to_sync(channel_layer.group_send)(self.group, { "type": "chat.message", "text": message, }) except UnicodeDecodeError: logger.error(traceback.format_exc()) message = dict() message['status'] = 0 # 拼接2次后还是报错则证明结果是乱码,强制转换 message['message'] = recv_message.decode('utf-8', 'ignore') channel_layer = get_channel_layer() async_to_sync(channel_layer.group_send)(self.group, { "type": "chat.message", "text": message, }) self.chan_cli.send(recv_message) try: data = recv_message.decode('utf-8') if self.tab_mode: tmp = data.split(' ') # tab 只返回一个命令时匹配 # print(tmp) if len(tmp) == 2 and tmp[1] == '' and tmp[0] != '': self.cmd_tmp = self.cmd_tmp + tmp[0].encode().replace(b'\x07', b'').decode() elif len(tmp) == 1 and tmp[0].encode() != b'\x07': # \x07 蜂鸣声 self.cmd_tmp = self.cmd_tmp + tmp[0].encode().replace(b'\x07', b'').decode() self.tab_mode = False if self.history_mode: # 不完善,只支持向上翻一个历史命令 # print(data) if data.strip() != '': self.cmd_tmp = data self.history_mode = False except Exception: pass # logger.error(traceback.format_exc()) # 记录操作录像 try: """ 防止 sz rz 传输文件时的报错 """ delay = round(time.time() - self.start_time, 6) self.res_asciinema.append(json.dumps([delay, 'o', recv_message.decode('utf-8')])) # 250条结果或者指定秒数就保存一次,这个任务可以优化为使用 celery if len(self.res_asciinema) > 2000 or int(time.time() - self.last_save_time) > 60 \ or sys.getsizeof(self.res_asciinema) > 2097152: tmp = list(self.res_asciinema) self.res_asciinema = [] self.last_save_time = time.time() res(self.res_file, tmp) except Exception: pass # logger.error(traceback.format_exc()) except socket.timeout: logger.error(traceback.format_exc()) if key.fileobj == self.chan_cli: try: send_message = self.chan_cli.recv(4096) if len(send_message) == 0: logger.info('客户端断开了连接 {}....'.format(self.client_addr)) # time.sleep(1) break else: if not self.lock: self.chan_ser.send(send_message) if not self.zmodem: try: data = send_message.decode('utf-8') if data == '\r': # 记录命令 data = '\n' if self.cmd_tmp.strip() != '': self.cmd_tmp += data self.cmd += self.cmd_tmp self.cmd_tmp = '' elif data.encode() == b'\x07': pass else: if data == '\t' or data.encode() == b'\x1b': # \x1b 点击2下esc键也可以补全 self.tab_mode = True elif data.encode() == b'\x1b[A' or data.encode() == b'\x1b[B': self.history_mode = True else: self.cmd_tmp += data except Exception: pass # logger.error(traceback.format_exc()) else: # 红色提示文字 self.chan_cli.send("\r\n\033[31m当前会话已被管理员锁定\033[0m\r\n") self.check_channel_window_change_request( self.chan_cli, self.width - 1, self.height, 0, 0 ) self.check_channel_window_change_request( self.chan_cli, self.width + 1, self.height, 0, 0 ) except socket.timeout: logger.error(traceback.format_exc()) except Exception: logger.error(traceback.format_exc()) break except socket.timeout: self.chan_cli.send("\r\n\033[31m由于长时间没有操作或者没有数据返回,连接已断开!\033[0m\r\n") logger.info("后端主机 (%s@%s) 会话由于长时间没有操作或者没有数据返回,连接断开!" % (self.ssh_args[2], self.ssh_args[0])) except Exception: logger.error(traceback.format_exc())
sheet1.write(0, 1, "RSSI") sheet1.write(0, 2, "Lattitude") sheet1.write(0, 3, "Longitude") sheet1.write(0, 4, "Center Freq.") sheet1.write(0, 5, "Date-time") book_index = 0 # Charts are independent of worksheets chart = book.add_chart({'type': 'line'}) chart.set_y_axis({'name': 'RSSI (dB)'}) chart.set_x_axis({'name': 'Center Frequency (MHz)'}) chart.set_title({'name': 'Frequency versus RSSI Plot'}) ################################################### mysel = selectors.DefaultSelector() keep_running = True sep = ' ' def read(connection, mask): "Callback for read events" global keep_running client_address = connection.getpeername() print('read({})'.format(client_address)) data = connection.recv(1024) if data: # A readable client socket has data print(' received {!r}'.format(data)) # connection.sendall(data)
def bridge(self): # 桥接 客户终端 和 代理服务终端 交互 # transport_keepalive(self.chan_ser.transport) sel = selectors.DefaultSelector( ) # 根据平台自动选择 IO 模式(kqueue, devpoll, epoll, poll, select) sel.register(self.chan_cli, selectors.EVENT_READ) sel.register(self.chan_ser, selectors.EVENT_READ) try: while self.chan_ser and self.chan_cli and not ( self.chan_ser.closed or self.chan_cli.closed): events = sel.select( timeout=terminal_exipry_time) # 指定时间无数据输入或者无数据返回则断开连接 if not events: raise socket.timeout for key, n in events: if key.fileobj == self.chan_ser: try: recv_message = self.chan_ser.recv(BufferSize) if self.zmodem: if zmodemszend in recv_message or zmodemrzend in recv_message: self.zmodem = False delay = round( time.time() - self.start_time, 6) self.res_asciinema.append( json.dumps([delay, 'o', '\r\n'])) # logger.info("zmodem end") if zmodemcancel in recv_message: self.zmodem = False self.chan_ser.send(b'\n') # logger.info("zmodem cancel") self.chan_cli.send(recv_message) continue else: if zmodemszstart in recv_message or zmodemrzstart in recv_message or \ zmodemrzestart in recv_message or zmodemrzsstart in recv_message or \ zmodemrzesstart in recv_message: self.zmodem = True # logger.info("zmodem start") self.chan_cli.send(recv_message) continue if len(recv_message) == 0: self.chan_cli.send( "\r\n\033[31m服务端已断开连接....\033[0m\r\n") time.sleep(1) break else: message = dict() message['status'] = 0 try: # 发送数据给查看会话的 websocket 组 message['message'] = recv_message.decode( 'utf-8') except UnicodeDecodeError: try: recv_message += self.chan_ser.recv(1) message[ 'message'] = recv_message.decode( 'utf-8') except UnicodeDecodeError: try: recv_message += self.chan_ser.recv( 1) message[ 'message'] = recv_message.decode( 'utf-8') except UnicodeDecodeError: logger.error( traceback.format_exc()) # 拼接2次后还是报错则证明结果是乱码,强制转换 message[ 'message'] = recv_message.decode( 'utf-8', 'ignore') self.chan_cli.send(recv_message) channel_layer = get_channel_layer() async_to_sync(channel_layer.group_send)( self.group, { "type": "chat.message", "text": message, }) delay = round(time.time() - self.start_time, 6) self.res_asciinema.append( json.dumps([ delay, 'o', recv_message.decode('utf-8') ])) # 250条结果或者指定秒数就保存一次,这个任务可以优化为使用 celery if len(self.res_asciinema) > 2000 or int(time.time() - self.last_save_time) > 60 \ or sys.getsizeof(self.res_asciinema) > 2097152: tmp = list(self.res_asciinema) self.res_asciinema = [] self.last_save_time = time.time() res(self.res_file, tmp) try: data = recv_message.decode('utf-8') if self.enter: self.enter = False if not data.startswith( "\r\n" ): # 回车后结果不以\r\n开头的肯定不是命令 self.cmd_tmp = '' else: if re.match( rb'^\r\n\s+\x1b.*$', recv_message ): # 终端为 xterm,linux 等显示颜色类型时在 vi 编辑模式下回车 self.cmd_tmp = '' # elif x == b'\r\n': # todo 正常模式下 vi 文件会返回 \r\n ,终端为 dumb 类型时在 vi 编辑模式下回车也会返回 \r\n, # self.cmd_tmp = '' else: # 记录真正命令, rl 不支持中文命令 cmd_time = time.strftime( "%Y-%m-%d %H:%M:%S", time.localtime( int(time.time()))) cmd = self.rl.process_line( self.cmd_tmp.encode( "utf-8")) if not cmd: # 有可能 rl 库会返回 None,重试一次 mp_readline.TESTING = True self.rl = mp_readline.MpReadline( ) cmd = self.rl.process_line( self.cmd_tmp.encode( "utf-8")) if cmd: self.cmd += cmd_time + "\t" + remove_control_chars( cmd) + '\n' else: logger.error( "recv from server: {} \nerror command: {}" .format( recv_message, self.cmd_tmp. encode("utf-8"))) self.cmd += cmd_time + "\t" + remove_control_chars( self.cmd_tmp) + '\n' self.cmd_tmp = '' else: if self.tab_mode: # todo 兼容有问题 self.tab_mode = False tmp = data.split(' ') # tab 只返回一个命令时匹配 # print(tmp) if len(tmp) == 2 and tmp[ 1] == '' and tmp[0] != '': self.cmd_tmp = self.cmd_tmp + tmp[ 0].encode().replace( b'\x07', b'').decode() elif len(tmp ) == 1 and tmp[0].encode( ) != b'\x07': # \x07 蜂鸣声 self.cmd_tmp = self.cmd_tmp + tmp[ 0].encode().replace( b'\x07', b'').decode() # 多次上下箭头查找历史命令返回数据中可能会包含 \x1b[1P 导致 rl 无法解析命令,具体原因没有深究 if self.history_mode: self.history_mode = False if recv_message != b'' and recv_message != b'\x07': recv_message = re.sub( rb'\x1b\[\d+P', b'', recv_message) self.cmd_tmp += recv_message.decode( "utf-8") if self.ctrl_c: # 取消命令 self.ctrl_c = False # if x == b'^C\r\n': if re.match( rb'^\^C\r\n[\s\S]*$', recv_message) or re.match( rb'^\r\n[\s\S]*$', recv_message): self.cmd_tmp = "" if self.ctrl_z: self.ctrl_z = False if re.match( rb'^[\s\S]*\[\d+\]\+\s+Stopped\s+\S+[\s\S]*$', recv_message): self.cmd_tmp = "" except Exception: logger.error(traceback.format_exc()) except socket.timeout: logger.error(traceback.format_exc()) if key.fileobj == self.chan_cli: try: send_message = self.chan_cli.recv(BufferSize) if len(send_message) == 0: logger.info('客户端断开了连接 {}....'.format( self.client_addr)) # time.sleep(1) break else: if not self.lock: self.chan_ser.send(send_message) if not self.zmodem: try: data = send_message.decode('utf-8') if data == '\r': # 回车,开始根据服务端返回判断是否是命令,这种判断方式的特性就导致了无法是否禁止命令功能,当然想绝对禁止命令本身就是一个伪命题 if self.cmd_tmp.strip() != '': self.enter = True elif data.encode( ) == b'\x07': # 响铃 pass elif data == '\t' or data.encode( ) == b'\x1b': # \x1b 点击2下esc键也可以补全 self.tab_mode = True elif data.encode( ) == b'\x1b[A' or data.encode( ) == b'\x1b[B': self.history_mode = True elif data.encode( ) == b'\x03': # 输入命令后先 ctrl + v,然后 ctrl + c 需要两次才能取消 self.ctrl_c = True elif data.encode( ) == b'\x1a': # ctrl + z self.ctrl_z = True else: self.cmd_tmp += data except Exception: logger.error( traceback.format_exc()) else: # 红色提示文字 self.chan_cli.send( "\r\n\033[31m当前会话已被管理员锁定\033[0m\r\n") self.check_channel_window_change_request( self.chan_cli, self.width - 1, self.height, 0, 0) self.check_channel_window_change_request( self.chan_cli, self.width + 1, self.height, 0, 0) except socket.timeout: logger.error(traceback.format_exc()) except Exception: logger.error(traceback.format_exc()) break except socket.timeout: self.chan_cli.send( "\r\n\033[31m由于长时间没有操作或者没有数据返回,连接已断开!\033[0m\r\n") logger.info("后端主机 (%s@%s) 会话由于长时间没有操作或者没有数据返回,连接断开!" % (self.ssh_args[2], self.ssh_args[0])) except Exception: logger.error(traceback.format_exc())
def __init__(self, config): self.config = config self.selector = selectors.DefaultSelector()
def __init__(self): self.daemon = self.sock = self._socketaddr = self.locationStr = self.pool = None self.shutting_down = False self.housekeeper = None self._selector = selectors.DefaultSelector()
def bridge(self): # 桥接 客户终端 和 代理服务终端 交互 # transport_keepalive(self.chan_ser.transport) sel = selectors.DefaultSelector() # Linux epol sel.register(self.chan_cli, selectors.EVENT_READ) sel.register(self.chan_ser, selectors.EVENT_READ) try: while self.chan_ser and self.chan_cli and not ( self.chan_ser.closed or self.chan_cli.closed): events = sel.select( timeout=terminal_exipry_time) # 指定时间无数据输入或者无数据返回则断开连接 if not events: raise socket.timeout for key, n in events: if key.fileobj == self.chan_ser: try: recv_message = self.chan_ser.recv(1024) if len(recv_message) == 0: self.chan_cli.send( "\r\n\033[31m服务端已断开连接....\033[0m\r\n") time.sleep(1) break else: try: # 发送数据给查看会话的 websocket 组 message = dict() message['status'] = 0 message['message'] = recv_message.decode( 'utf-8') channel_layer = get_channel_layer() async_to_sync(channel_layer.group_send)( self.group, { "type": "chat.message", "text": message, }) except Exception: logger.error(traceback.format_exc()) self.chan_cli.send(recv_message) try: data = recv_message.decode('utf-8') if self.tab_mode: tmp = data.split(' ') # tab 只返回一个命令时匹配 # print(tmp) if len(tmp) == 2 and tmp[ 1] == '' and tmp[0] != '': self.cmd_tmp = self.cmd_tmp + tmp[ 0].encode().replace( b'\x07', b'').decode() elif len(tmp) == 1 and tmp[0].encode( ) != b'\x07': # \x07 蜂鸣声 self.cmd_tmp = self.cmd_tmp + tmp[ 0].encode().replace( b'\x07', b'').decode() self.tab_mode = False if self.history_mode: # 不完善,只支持向上翻一个历史命令 # print(data) if data.strip() != '': self.cmd_tmp = data self.history_mode = False except Exception: pass # logger.error(traceback.format_exc()) # 记录操作录像 try: """ 防止 sz rz 传输文件时的报错 """ delay = round( time.time() - self.start_time, 6) self.res_asciinema.append( json.dumps([ delay, 'o', recv_message.decode('utf-8') ])) # 250条结果或者指定秒数就保存一次,这个任务可以优化为使用 celery if len(self.res_asciinema) > 250 or int( time.time() - self.last_save_time) > 30: tmp = list(self.res_asciinema) self.res_asciinema = [] self.last_save_time = time.time() if platform.system().lower( ) == 'linux': celery_save_res_asciinema.delay( settings.MEDIA_ROOT + '/' + self.res_file, tmp) else: with open( settings.MEDIA_ROOT + '/' + self.res_file, 'a+') as f: for line in tmp: f.write( '{}\n'.format(line)) except Exception: pass # logger.error(traceback.format_exc()) except socket.timeout: logger.error(traceback.format_exc()) if key.fileobj == self.chan_cli: try: send_message = self.chan_cli.recv(1024) if len(send_message) == 0: logger.info('客户端断开了连接 {}....'.format( self.client_addr)) # time.sleep(1) break else: if not self.lock: self.chan_ser.send(send_message) try: data = send_message.decode('utf-8') if data == '\r': # 记录命令 data = '\n' if self.cmd_tmp.strip() != '': self.cmd_tmp += data self.cmd += self.cmd_tmp # print('-----------------------------------') # print(self.cmd_tmp) # print(self.cmd_tmp.encode()) # print('-----------------------------------') self.cmd_tmp = '' elif data.encode() == b'\x07': pass else: if data == '\t' or data.encode( ) == b'\x1b': # \x1b 点击2下esc键也可以补全 self.tab_mode = True elif data.encode( ) == b'\x1b[A' or data.encode( ) == b'\x1b[B': self.history_mode = True else: self.cmd_tmp += data except Exception: logger.error(traceback.format_exc()) else: # 红色提示文字 self.chan_cli.send( "\r\n\033[31m当前会话已被管理员锁定\033[0m\r\n") self.check_channel_window_change_request( self.chan_cli, self.width - 1, self.height, 0, 0) self.check_channel_window_change_request( self.chan_cli, self.width + 1, self.height, 0, 0) except socket.timeout: logger.error(traceback.format_exc()) except Exception: logger.error(traceback.format_exc()) break except socket.timeout: self.chan_cli.send( "\r\n\033[31m由于长时间没有操作或者没有数据返回,连接已断开!\033[0m\r\n") logger.info("后端主机 (%s@%s) 会话由于长时间没有操作或者没有数据返回,连接断开!" % (self.ssh_args[2], self.ssh_args[0])) except Exception: logger.error(traceback.format_exc())