本文目录导读:

- 方法1:使用
schedule库(推荐) - 方法2:使用
APScheduler库(功能更强大) - 方法3:使用
cron或 Windows 任务计划(系统级别) - 方法4:使用守护进程方式
- 安装依赖
- 最佳实践建议
我来介绍几种Python定时清理过期日志的方法:
方法1:使用 schedule 库(推荐)
import os
import time
import schedule
from datetime import datetime, timedelta
def clean_logs(log_dir, days_keep=30):
"""
清理指定目录下过期的日志文件
Args:
log_dir: 日志目录路径
days_keep: 保留最近多少天的日志
"""
if not os.path.exists(log_dir):
print(f"目录不存在: {log_dir}")
return
cutoff_date = datetime.now() - timedelta(days=days_keep)
cleaned_count = 0
for filename in os.listdir(log_dir):
file_path = os.path.join(log_dir, filename)
# 跳过目录
if os.path.isdir(file_path):
continue
# 获取文件的最后修改时间
file_mtime = datetime.fromtimestamp(os.path.getmtime(file_path))
# 如果文件修改时间早于阈值,删除
if file_mtime < cutoff_date:
try:
os.remove(file_path)
cleaned_count += 1
print(f"已删除: {filename} (最后修改: {file_mtime})")
except Exception as e:
print(f"删除失败 {filename}: {e}")
print(f"清理完成,共删除 {cleaned_count} 个文件")
# 每天凌晨3点执行清理
schedule.every().day.at("03:00").do(clean_logs, log_dir="/var/log/app", days_keep=30)
# 也可以每隔X小时执行
# schedule.every(6).hours.do(clean_logs, log_dir="/var/log/app", days_keep=30)
# 定时任务循环
if __name__ == "__main__":
print("日志清理服务已启动...")
while True:
schedule.run_pending()
time.sleep(60) # 每分钟检查一次
方法2:使用 APScheduler 库(功能更强大)
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.cron import CronTrigger
import os
from datetime import datetime, timedelta
import logging
# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def clean_expired_logs(log_dir, days_keep=30, patterns=['*.log', '*.txt']):
"""
清理过期日志文件
Args:
log_dir: 日志目录
days_keep: 保留天数
patterns: 文件匹配模式
"""
import glob
logger.info(f"开始清理 {log_dir} 下的过期日志...")
cutoff_date = datetime.now() - timedelta(days=days_keep)
cleaned_count = 0
total_size = 0
for pattern in patterns:
for file_path in glob.glob(os.path.join(log_dir, pattern)):
if os.path.isfile(file_path):
file_mtime = datetime.fromtimestamp(os.path.getmtime(file_path))
if file_mtime < cutoff_date:
try:
file_size = os.path.getsize(file_path)
os.remove(file_path)
cleaned_count += 1
total_size += file_size
logger.debug(f"已删除: {file_path}")
except Exception as e:
logger.error(f"删除失败 {file_path}: {e}")
logger.info(f"清理完成: 删除 {cleaned_count} 个文件,释放 {total_size/1024/1024:.2f} MB")
# 创建调度器
scheduler = BlockingScheduler()
# 添加定时任务:每天早上3点执行
scheduler.add_job(
clean_expired_logs,
CronTrigger(hour=3, minute=0), # 每天3:00
args=["/var/log/app", 30, ['*.log']],
id="clean_logs_job"
)
# 也可以添加多个任务
scheduler.add_job(
clean_expired_logs,
CronTrigger(day_of_week="mon", hour=1, minute=0), # 每周一1:00
args=["/var/log/backup", 7, ['*.log', '*.txt']],
id="clean_backup_logs"
)
if __name__ == "__main__":
print("APScheduler 日志清理服务启动...")
try:
scheduler.start()
except KeyboardInterrupt:
print("服务停止")
方法3:使用 cron 或 Windows 任务计划(系统级别)
创建独立的Python脚本 log_cleaner.py:
#!/usr/bin/env python3
"""
日志清理脚本 - 配合cron或Windows任务计划使用
"""
import os
import sys
import argparse
from datetime import datetime, timedelta
import logging
def setup_logging(log_file=None):
"""配置日志"""
handlers = [logging.StreamHandler()]
if log_file:
handlers.append(logging.FileHandler(log_file))
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=handlers
)
def clean_directory(directory, days_keep=30, dry_run=False):
"""
清理指定目录的过期文件
Returns:
tuple: (删除文件数, 释放空间byte)
"""
logger = logging.getLogger(__name__)
if not os.path.exists(directory):
logger.error(f"目录不存在: {directory}")
return 0, 0
cutoff_date = datetime.now() - timedelta(days=days_keep)
cleaned_count = 0
total_size = 0
for root, dirs, files in os.walk(directory):
for file in files:
file_path = os.path.join(root, file)
# 只处理.log和.txt文件
if not (file.endswith('.log') or file.endswith('.txt')):
continue
try:
file_mtime = datetime.fromtimestamp(os.path.getmtime(file_path))
if file_mtime < cutoff_date:
file_size = os.path.getsize(file_path)
if dry_run:
logger.info(f"[模拟] 将要删除: {file_path} ({file_size/1024:.1f} KB)")
else:
os.remove(file_path)
logger.info(f"已删除: {file_path} ({file_size/1024:.1f} KB)")
cleaned_count += 1
total_size += file_size
except OSError as e:
logger.error(f"处理文件失败 {file_path}: {e}")
return cleaned_count, total_size
def main():
parser = argparse.ArgumentParser(description='清理过期日志文件')
parser.add_argument('-d', '--directory', required=True,
help='日志目录路径')
parser.add_argument('--days', type=int, default=30,
help='保留最近N天的日志 (默认: 30)')
parser.add_argument('--dry-run', action='store_true',
help='模拟运行,不实际删除')
parser.add_argument('--log-file', help='清理日志输出文件')
args = parser.parse_args()
# 设置日志
setup_logging(args.log_file)
logger = logging.getLogger(__name__)
logger.info(f"开始清理: {args.directory}")
logger.info(f"保留天数: {args.days} 天")
if args.dry_run:
logger.info("运行模式: 模拟 (不会真正删除)")
count, size = clean_directory(args.directory, args.days, args.dry_run)
logger.info(f"清理完成: 删除 {count} 个文件,释放 {size/1024/1024:.2f} MB")
if __name__ == "__main__":
main()
配合系统定时任务使用
Linux (crontab):
# 编辑crontab crontab -e # 每天凌晨3点执行 0 3 * * * /usr/bin/python3 /path/to/log_cleaner.py -d /var/log/app --days 30 --log-file /var/log/log_cleaner.log
Windows (任务计划程序):
schtasks /create /tn "CleanLogs" /tr "python D:\scripts\log_cleaner.py -d D:\logs --days 30" /sc daily /st 03:00
方法4:使用守护进程方式
#!/usr/bin/env python3
"""
日志清理守护进程
"""
import daemon
import time
import signal
import sys
from datetime import datetime, timedelta
import os
import logging
class LogCleanerDaemon:
def __init__(self, log_dir, days_keep=30, interval_hours=24):
self.log_dir = log_dir
self.days_keep = days_keep
self.interval_hours = interval_hours
self.running = True
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('/var/log/log_cleaner_daemon.log'),
logging.StreamHandler()
]
)
self.logger = logging.getLogger(__name__)
def clean(self):
"""执行清理"""
cutoff_date = datetime.now() - timedelta(days=self.days_keep)
cleaned = 0
for filename in os.listdir(self.log_dir):
file_path = os.path.join(self.log_dir, filename)
if os.path.isfile(file_path):
file_mtime = datetime.fromtimestamp(os.path.getmtime(file_path))
if file_mtime < cutoff_date:
try:
os.remove(file_path)
cleaned += 1
except Exception as e:
self.logger.error(f"删除失败 {file_path}: {e}")
self.logger.info(f"清理完成,删除 {cleaned} 个文件")
def run(self):
"""运行守护进程"""
self.logger.info("日志清理守护进程启动")
def signal_handler(signum, frame):
self.logger.info("接收到停止信号")
self.running = False
signal.signal(signal.SIGTERM, signal_handler)
signal.signal(signal.SIGINT, signal_handler)
while self.running:
try:
self.clean()
time.sleep(self.interval_hours * 3600)
except Exception as e:
self.logger.error(f"清理过程出错: {e}")
time.sleep(60) # 出错后等待1分钟重试
if __name__ == "__main__":
# 以守护进程方式运行
with daemon.DaemonContext():
cleaner = LogCleanerDaemon("/var/log/app", days_keep=30, interval_hours=24)
cleaner.run()
安装依赖
# 方法1需要的库 pip install schedule # 方法2需要的库 pip install apscheduler # 方法4需要的库 pip install python-daemon
最佳实践建议
- 先测试再部署:使用
--dry-run参数模拟运行 - 保留备份:删除前可先压缩归档
- 监控清理效果:记录清理日志
- 处理异常情况:添加错误处理和重试机制
- 考虑日志轮转:配合 logrotate 使用效果更好
选择哪种方法取决于你的具体需求:
- 简单场景:使用
schedule库 - 复杂定时需求:使用
APScheduler - 生产环境:使用系统级 cron 或 systemd timer
- 需要持久运行:使用守护进程方式
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播