Files
yakpanel-core/script/run_log_split.py
2026-04-07 02:04:22 +05:30

171 lines
6.2 KiB
Python

#!/usr/bin/python
# coding: utf-8
# -----------------------------
# Website run log split script
# -----------------------------
import sys
import os
import time
import glob
os.chdir("/www/server/panel")
if '/www/server/panel' not in sys.path:
sys.path.insert(0,'/www/server/panel')
if '/www/server/panel/class' not in sys.path:
sys.path.insert(0,'class/')
if '/www/server/panel/class_v2' not in sys.path:
sys.path.insert(0,'class_v2/')
import public, json
try:
from projectModelV2.pythonModel import main as pythonMod
from projectModelV2.nodejsModel import main as nodejsMod
mods = {
"python": pythonMod(),
"node": nodejsMod(),
}
except Exception as e:
print(str(e))
print("****** project split log task error ******")
print('==================================================================')
print('★[' + time.strftime("%Y/%m/%d %H:%M:%S") + '] split log task start ★')
print('==================================================================')
class LogSplit:
__slots__ = ("stype", "log_size", "limit", "_time", "compress", "exclude_sites")
@classmethod
def build_log_split(cls, name):
logsplit = cls()
path = '{}/data/run_log_split.conf'.format(public.get_panel_path())
data = {}
if os.path.exists(path):
try:
data = json.loads(public.readFile(path))
except:
public.ExecShell("rm -f {}".format(path))
return "file not found"
_clean(data)
public.writeFile(path, json.dumps(data))
target = data.get(name)
if not target :
return "file not found"
else:
for i in cls.__slots__:
if i in target:
setattr(logsplit, i, target[i])
logsplit._show()
return logsplit
def __init__(self, split_type: str = "day", limit: int = 180, log_size: int = 1024, compress: bool = False) -> None:
self.stype = split_type
self.log_size = log_size
self.limit = limit
self._time = time.strftime("%Y-%m-%d_%H%M%S")
self.compress = compress
self.exclude_sites = []
def _show(self):
if self.stype == "day":
print('|---Split method: Split 1 copy per day')
else:
print('|---Split method: Split by file size, split when file exceeds {}'.format(public.to_size(self.log_size)))
print('|---Currently keeping the latest [{}] copies'.format(self.limit))
def _to_zip(self, file_path):
os.system('gzip {}'.format(file_path))
def _del_surplus_log(self, history_log_path, log_prefix):
if not os.path.exists(history_log_path):
os.makedirs(history_log_path, mode=0o755)
logs = sorted(glob.glob(history_log_path + '/' + log_prefix + "*_log.*"))
count = len(logs)
if count >= self.limit:
for i in logs[:count - self.limit + 1]:
if os.path.exists(i):
os.remove(i)
print('|---Surplus log [' + i + '] has been deleted!')
def __call__(self, pjanme: str, sfile: str, log_prefix: str):
base_path, filename = sfile.rsplit("/", 1)
history_log_path = '{}/{}-history_logs'.format(base_path, pjanme)
if self.stype == 'size' and os.path.getsize(sfile) < self.log_size:
print('|---File size has not exceeded [{}], skipping!'.format(public.to_size(self.log_size)))
return
self._del_surplus_log(history_log_path, log_prefix)
if os.path.exists(sfile):
history_log_file = history_log_path + '/' + log_prefix + '_' + self._time + '_log.log'
if not os.path.exists(history_log_file):
with open(history_log_file, 'wb') as hf, open(sfile, 'r+b') as lf:
while True:
chunk_data = lf.read(1024*100)
if not chunk_data:
break
hf.write(chunk_data)
lf.seek(0)
lf.truncate()
if self.compress:
self._to_zip(history_log_file)
print('|---Log has been split to: ' + history_log_file + (".gz" if self.compress else ""))
else:
print('|---Target log file {} for project {} is missing, please note'.format(sfile, pjanme))
def main(name):
logsplit = LogSplit.build_log_split(name)
if logsplit=="file not found":
print(
"****** Detected panel project log split task configuration is empty,"
" please reset project log split task ******"
)
return
if not logsplit:
print("****** Panel project log split task configuration file is missing ******")
return
project = public.M('sites').where("project_type <> ? and name = ?", ("PHP", name)).find()
project['project_config'] = json.loads(project['project_config'])
for_split_func = getattr(mods.get(project["project_type"].lower()), "for_split")
if callable(for_split_func):
print('|---Starting to operate on {} project [{}] logs'.format(project["project_type"], project["name"]))
try:
for_split_func(logsplit, project)
print('|---Completed log split task for {} project [{}]'.format(project["project_type"], project["name"]))
except:
import traceback
print(traceback.format_exc())
print('|---Log split task error for {} project [{}]'.format(project["project_type"], project["name"]))
else:
print("****** Panel project log split task error ******")
print('================= All log split tasks completed ==================')
def _clean(data):
res = public.M('crontab').field('name').select()
del_config = []
for i in data.keys():
for j in res:
if j["name"].find(i) != -1 and j["name"].find("log split"):
break
else:
del_config.append(i)
for i in del_config:
del data[i]
if __name__ == '__main__':
if len(sys.argv) == 2:
name = sys.argv[1].strip()
main(name)
else:
print("****** Panel project log split task configuration parameter error ******")