diff --git a/apps/ops/templates/ops/celery_task_log.html b/apps/ops/templates/ops/celery_task_log.html index c7f177c6e..455fc28d6 100644 --- a/apps/ops/templates/ops/celery_task_log.html +++ b/apps/ops/templates/ops/celery_task_log.html @@ -6,15 +6,37 @@ +
@@ -36,7 +58,8 @@ cursorBlink: false, screenKeys: false, fontFamily: '"Monaco", "Consolas", "monospace"', - fontSize: 12, + fontSize: 13, + lineHeight: 1.2, rightClickSelectsWord: true, disableStdin: true }); diff --git a/apps/ops/templates/ops/command_execution_create.html b/apps/ops/templates/ops/command_execution_create.html index 9176c608d..cd1867c74 100644 --- a/apps/ops/templates/ops/command_execution_create.html +++ b/apps/ops/templates/ops/command_execution_create.html @@ -34,6 +34,27 @@ .select2-container .select2-selection--single { height: 34px; } + + .terminal .xterm-viewport { + background-color: #1f1b1b; + overflow: auto; + } + + body ::-webkit-scrollbar-track { + -webkit-box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.3); + background-color: #272323; + border-radius: 6px; + } + + body ::-webkit-scrollbar { + width: 8px; + height: 8px; + } + + body ::-webkit-scrollbar-thumb { + background-color: #494141; + border-radius: 6px; + } {% endblock %} @@ -201,11 +222,10 @@ cursorBlink: false, screenKeys: false, fontFamily: 'monaco, Consolas, "Lucida Console", monospace', - fontSize: 14, - lineHeight: 1, + fontSize: 13, rightClickSelectsWord: true, disableStdin: true, - cursorBlink: false, + lineHeight: 1.2, theme: { background: '#1f1b1b' } diff --git a/apps/ops/ws.py b/apps/ops/ws.py index d6bff86a7..cd2fa33bb 100644 --- a/apps/ops/ws.py +++ b/apps/ops/ws.py @@ -23,40 +23,46 @@ class CeleryLogWebsocket(JsonWebsocketConsumer): if task_id: self.handle_task(task_id) + def wait_util_log_path_exist(self, task_id): + log_path = get_celery_task_log_path(task_id) + while not self.disconnected: + if not os.path.exists(log_path): + self.send_json({'message': '.', 'task': task_id}) + time.sleep(0.5) + continue + self.send_json({'message': '\r\n'}) + try: + logger.debug('Task log path: {}'.format(log_path)) + task_log_f = open(log_path, 'rb') + return task_log_f + except OSError: + return None + + def read_log_file(self, task_id): + task_log_f = self.wait_util_log_path_exist(task_id) + if not task_log_f: + return + + task_end_mark = [] + while not self.disconnected: + data = task_log_f.read(4096) + if data: + data = data.replace(b'\n', b'\r\n') + self.send_json( + {'message': data.decode(errors='ignore'), 'task': task_id}) + if data.find(b'succeeded in') != -1: + task_end_mark.append(1) + if data.find(bytes(task_id, 'utf8')) != -1: + task_end_mark.append(1) + elif len(task_end_mark) == 2: + logger.debug('Task log end: {}'.format(task_id)) + break + time.sleep(0.2) + task_log_f.close() + def handle_task(self, task_id): logger.info("Task id: {}".format(task_id)) - log_path = get_celery_task_log_path(task_id) - - def func(): - task_log_f = None - - while not self.disconnected: - if not os.path.exists(log_path): - self.send_json({'message': '.', 'task': task_id}) - time.sleep(0.5) - continue - self.send_json({'message': '\r\n'}) - try: - logger.debug('Task log path: {}'.format(log_path)) - task_log_f = open(log_path, 'rb') - break - except OSError: - return - - if not task_log_f: - return - - while not self.disconnected: - data = task_log_f.readline() - - if data: - data = data.replace(b'\n', b'\r\n') - self.send_json({'message': data.decode(errors='ignore'), 'task': task_id}) - if data.startswith(b'Task') and data.find(b'succeeded'): - break - time.sleep(0.1) - task_log_f.close() - thread = threading.Thread(target=func) + thread = threading.Thread(target=self.read_log_file, args=(task_id,)) thread.start() def disconnect(self, close_code):