宝塔面板很好用,新手基本都可以无痛使用。但是最近用了新的宝塔面板以后,发现日志分割功能不起作用了,找到了分割日志的代码文件:/www/server/panel/script/rotate_log.py。查看代码,发现是代码出了问题,首先把宝塔面板与日志分割相关的代码贴出来:
import os ,sys
import glob
import time
import shutil
import json
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/')
import public
class LogSplit():
def __init__(self, split_type="day", log_size=1024*1024*10, limit=180, compress=False):
# 初始化LogSplit对象
self.stype = split_type # 设置切割类型(每天或按大小)
self.log_size = log_size # 设置日志文件的切割大小阈值
self.limit = limit # 设置保留的日志文件数量
self.compress = compress # 设置是否压缩日志文件
self._time = time.strftime("%Y-%m-%d_%H%M%S") # 获取当前时间,用于生成文件名
def split_logs(self, directory):
self._start()
self._show()
# 切割指定目录下的所有日志文件
counter=0
for logfile in glob.glob(os.path.join(directory, '*.log')):
task_name = '[勿删]切割计划任务日志'
echo=public.M('crontab').where('name=?', (task_name,)).find()['echo']
cron_file="/www/server/cron/{}.log".format(echo)
if logfile!=cron_file:
self.process_log_file(logfile) # 处理每一个日志文件
counter+=1
if counter==0:
print()
print("|---暂无日志文件可以处理")
self._stop()
def process_log_file(self, logfile):
print()
print(f"|---开始处理日志文件:{logfile}")
if os.path.getsize(logfile) < self.log_size and self.stype == 'size':
print(f"|---跳过文件 {logfile},文件大小未达到设定的切割阈值{public.to_size(self.log_size)}")
return
base_path, filename = os.path.split(logfile)
log_identifier = filename.split('.')[0]+"_log"
new_directory = os.path.join(base_path, log_identifier)
# 检查同名文件是否存在,如果存在且不是目录,则删除
if os.path.exists(new_directory):
if not os.path.isdir(new_directory):
# print(f"存在同名文件,正在删除:{new_directory}")
os.remove(new_directory)
# 确保目录存在
if not os.path.exists(new_directory):
# print(f"创建目录:{new_directory}")
os.makedirs(new_directory)
else:
# print(f"目录已存在:{new_directory}")
pass
# 创建新的日志文件路径
new_log_file = os.path.join(new_directory, f"{self._time}.log")
# print(f"新日志文件将被创建于:{new_log_file}")
# 移动日志文件
try:
shutil.move(logfile, new_log_file)
print(f"|---日志文件 {logfile} 已被切割并移动到 {new_log_file}")
# 压缩日志文件
if self.compress:
os.system(f'gzip "{new_log_file}"')
print(f"|---日志文件已被压缩:{new_log_file}.gz")
self.manage_old_logs(new_directory)
except Exception as e:
print(f"|---在移动或压缩文件时发生错误:{e}")
def _start(self):
print('==================================================================')
print('★[' + time.strftime("%Y/%m/%d %H:%M:%S") + ']切割计划任务日志')
print('==================================================================')
def _show(self):
if self.stype == "day":
print('|---切割方式: 每天切割1份')
else:
print('|---切割方式: 按文件大小切割,文件超过{}开始切割'.format(public.to_size(self.log_size)))
print('|---当前保留最新的[{}]份'.format(self.limit))
def _stop(self):
print()
print('=================已完成所有日志切割任务==================')
def manage_old_logs(self, directory):
# 获取目录中所有的日志文件
files = sorted(glob.glob(os.path.join(directory, '*')),
key=os.path.getmtime,
reverse=True)
# 如果文件数量超过限制,则删除最旧的文件
if len(files) > self.limit:
print("|---检测到旧文件数量超过限制,开始删除旧的文件.....")
for old_file in files[self.limit:]:
os.remove(old_file)
# print(f"删除旧日志文件:{old_file}")
print("|---删除旧文件成功")
def load_config(config_path):
if not os.path.exists(config_path):
default_config = {
"log_size": 0,
"hour": "2",
"minute": "0",
"num": 10,
"compress": False,
"stype": "day"
}
with open(config_path, 'w') as config_file:
json.dump(default_config, config_file, indent=4)
return default_config
with open(config_path, 'r') as config_file:
config = json.load(config_file)
if not config:
config = {
"log_size": 0,
"hour": "2",
"minute": "0",
"num": 10,
"compress": False,
"stype": "day"
}
return config
def main():
config_path = '/www/server/panel/data/crontab_log_split.conf' # 配置文件路径
config = load_config(config_path) # 加载配置
log_splitter = LogSplit(
split_type='day' if config['log_size'] == 0 else 'size', # 根据配置决定切割类型
log_size=float(config['log_size']), # 设置日志大小阈值
limit=int(config['num']), # 设置文件保留数量
compress=config['compress'] # 设置是否压缩
)
log_directory = '/www/server/cron' # 日志文件目录
log_splitter.split_logs(log_directory) # 执行日志切割
if __name__ == '__main__':
main() # 程序入口
我首先是把代码发给豆包,请豆包给我改,结果改来改去都不行。后面只好自己读代码了,终于找到了问题所在。一共两处问题,在上面的代码中标红的位置。
第一处错误:
log_directory = '/www/server/cron' # 日志文件目录
这里是明显错误的,因为宝塔的日志文件默认就没有放在这个目录,这里应该修改为:
log_directory = ‘/www/wwwlogs’ # 日志文件目录
第二处错误:
shutil.move(logfile, new_log_file)
这里是把日志文件直接移动到了生成的日志文件目录,会导致系统仍然把新的内容写到这个文件中,起不到分割的作用。应该改成:
shutil.copy2(logfile, new_log_file)
#注释了上面那句,是因为上面是直接移动了文件,导致原目录里面没有新的日志生成了。这不是我想要的。新加的这句是复制源文件到目标文件
# 以写入模式打开文件,会自动清空内容
with open(logfile, 'w') as f:
pass
# 不写入任何内容,相当于清空文件
改好测试无误,特此记录!