171 lines
6.2 KiB
Python
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 ******")
|