应自定义归档逻辑:用TimedRotatingFileHandler配合doRollover,或启动前按修改时间将旧日志移至日期子目录,注意避免竞态、路径绝对化及环境一致性。

日志文件按天切割后怎么自动归档到子目录
Python 默认的 RotatingFileHandler 或 TimedRotatingFileHandler 只能轮转文件名(比如加日期后缀),但不会自动创建 2024-06-15/ 这样的日期子目录。得自己接管归档逻辑。
推荐用 logging.handlers.TimedRotatingFileHandler 配合自定义 doRollover 方法,或者更简单:在每次启动爬虫前,把昨天的日志挪进对应日期目录。
- 检查
os.path.getmtime(log_path)获取最后修改时间,转成日期字符串作为目标目录名 - 用
os.makedirs(f"logs/{date_str}", exist_ok=True)确保目录存在 - 用
shutil.move(log_path, f"logs/{date_str}/crawler_{date_str}.log")搬走旧日志 - 注意:如果爬虫每小时跑一次,别重复归档同一份日志——加个
.archived标记文件或记录到archive_state.json
用 logging.basicConfig 时怎么避免日志写错位置
很多人直接写 logging.basicConfig(filename="app.log"),结果发现日志没进预期目录,甚至写到 Python 安装路径下。根本原因是相对路径基于当前工作目录(os.getcwd()),而 cron 或 systemd 启动时工作目录不固定。
必须显式指定绝对路径,且最好从脚本所在位置推导:
立即学习“Python免费学习笔记(深入)”;
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 用
Path(__file__).parent / "logs" / "crawler.log"(需from pathlib import Path) - 不要用
os.path.join(os.getcwd(), ...)——os.getcwd()不可靠 - 归档脚本里也要统一用这个路径逻辑,否则搬日志时找不见源文件
- 如果部署在 Docker 里,确保
logs/目录已挂载为 volume,否则归档后日志会丢失
crontab 自动运行归档脚本总失败怎么办
典型现象是手动执行 python archive_logs.py 没问题,但加到 crontab 就报 ModuleNotFoundError 或找不到日志文件——本质是环境不一致。
- crontab 默认没有加载用户的 shell profile,
PYTHONPATH、PATH都不完整;在 crontab 条目里显式指定解释器和环境:0 0 * * * cd /opt/crawler && /usr/bin/python3 /opt/crawler/archive_logs.py >> /var/log/crawler/archive.log 2>&1 - 脚本开头加
#!/usr/bin/env python3不管用,crontab 不读 shebang - 所有路径用绝对路径,包括日志路径、归档目录、临时标记文件
- 加一句
import sys; print("Python path:", sys.executable)到日志里,确认 cron 调用的是哪个 Python
归档后原日志还在写,新日志却空了
这是最常见的资源竞争问题:归档脚本把正在被 FileHandler 写入的文件移走了,但 handler 还拿着旧文件描述符,继续往已被移动的 inode 写——表面看新日志空,其实是写进了已归档文件里。
解决方案不是“等它写完再搬”,而是让日志系统配合归档节奏:
- 爬虫主程序结束前调用
logging.shutdown(),确保 buffer 刷盘、文件句柄关闭 - 归档脚本先检查
ps aux | grep crawler(Linux)或pgrep -f crawler.py,确认进程已退出 - 更稳妥的做法:爬虫用
logging.FileHandler+ 每次启动生成唯一文件名(如f"crawler_{int(time.time())}.log"),归档脚本只处理“已完成”的旧文件(比如修改时间早于 5 分钟) - 别依赖文件锁——
fcntl.flock在 NFS 或容器里可能失效
归档逻辑看着简单,真正踩坑的点都在路径解析、进程生命周期和文件句柄状态上。尤其当爬虫本身用多进程或异步写日志时,logging 模块的线程安全不等于进程安全,得靠外部协调。

















