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):