File size: 5,683 Bytes
020c337 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | # coding: utf-8
# -------------------------------------------------------------------
# 宝塔Linux面板
# -------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
# -------------------------------------------------------------------
# Author: wzz <wzz@bt.cn>
# -------------------------------------------------------------------
# docker模型sock 封装库 容器库
# -------------------------------------------------------------------
import socket
import select
import json
import public
from btdockerModel.dockerSock.sockBase import base
class dockerContainer(base):
def __init__(self):
super(dockerContainer, self).__init__()
# 2024/3/13 上午 11:20 获取所有容器列表
def get_container(self):
'''
@name 获取所有容器列表
@author wzz <2024/3/13 上午 10:54>
@param "data":{"参数名":""} <数据类型> 参数描述
@return dict{"status":True/False,"msg":"提示信息"}
'''
try:
return json.loads(public.ExecShell("curl -s --unix-socket {} http:/{}/containers/json?all=1".format(self._sock, self.get_api_version()))[0])
except Exception as e:
try:
c_list = public.ExecShell("whereis curl | awk 'print {$1}'")[0].split(" ")
for c in c_list:
if not c.endswith("/curl"): continue
res, err = public.ExecShell("{} -s --unix-socket {} http:/{}/containers/json?all=1".format(c, self._sock, self.get_api_version()))
if not err: return json.loads(res)
return []
except:
return []
# 2024/3/28 下午 11:37 获取指定容器的inspect
def get_container_inspect(self, container_id: str):
'''
@name 获取指定容器的inspect
@param container_id: 容器id
@return dict{"status":True/False,"msg":"提示信息"}
'''
try:
return json.loads(public.ExecShell("curl -s --unix-socket {} http:/{}/containers/{}/json".format(self._sock, self.get_api_version(), container_id))[0])
except Exception as e:
try:
c_list = public.ExecShell("whereis curl | awk 'print {$1}'")[0].split(" ")
for c in c_list:
if not c.endswith("/curl"): continue
res, err = public.ExecShell("{} -s --unix-socket {} http:/{}/containers/{}/json".format(c, self._sock, self.get_api_version(), container_id))
if not err: return json.loads(res)
return []
except:
return []
# 2025/1/18 11:05 构造返回日志
def structure_docker_logs(self, log_data: str) -> list:
"""
@name: 清理 Docker 日志并转换为 JSON 格式
@param: raw_logs: 原始日志字符串
@return: 日志对象列表
"""
formatted_logs = []
# 逐行处理日志
for line in log_data.split('\n'):
line = line.strip()
if line:
# 只处理包含日期时间戳的行,去除其它无用的字符
parts = line.split(' ', 1) # 按第一个空格分割时间戳和日志内容
if len(parts) > 1:
timestamp = parts[0]
message = parts[1]
formatted_logs.append(message)
# 返回格式化后的日志
return "\n".join(formatted_logs)
# 2025/1/18 10:26 获取容器日志
def get_container_logs(self, container_id: str, options: dict) -> list:
'''
@name 获取容器日志
@param container_id: 容器id
@return dict{"status":True/False,"msg":"提示信息"}
'''
# 定义 Docker API 请求路径
url = f"/containers/{container_id}/logs?stdout=true&stderr=true×tamps=true"
if options:
if "since" in options and options["since"] != "":
url += "&since={}".format(options['since'])
if "until" in options and options["until"] != "":
url += "&until={}".format(options['until'])
if "tail" in options and options["tail"] != "":
url += "&tail={}".format(options['tail'])
# 设置 Unix socket 地址
unix_socket = "/var/run/docker.sock"
# 连接到 Docker 的 UNIX socket
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as client_socket:
client_socket.settimeout(1)
client_socket.connect(unix_socket)
# 构建 HTTP 请求
http_request = f"GET {url} HTTP/1.1\r\n"
http_request += "Host: localhost\r\n"
http_request += "Accept: application/json\r\n"
http_request += "Content-Type: application/json\r\n"
http_request += "Connection: close\r\n\r\n"
# 发送请求
client_socket.sendall(http_request.encode())
# 接收响应
response = b""
while True:
data = client_socket.recv(4096)
if not data:
break
response += data
# 从响应中分割出 HTTP 头部和响应体
headers, body = response.split(b"\r\n\r\n", 1)
# 只保留日志部分,解码并忽略无法解码的字符
log_data = body.decode('utf-8', errors='replace')
result = self.structure_docker_logs(log_data)
# 返回日志内容
return result
|