Python自动清理过期日志脚本_os模块与文件路径操作实践
应先用 os.path.isdir() 校验日志目录存在且为目录,再用绝对路径调用 os.listdir();遍历时用 os.path.isfile() 过滤文件,删除时据类型选 os.remove() 或 shutil.rmtree(),并记录具体错误。
如何用 os.listdir() 安全获取日志目录下的文件列表
直接遍历目录前,必须先确认路径存在且是目录,否则 os.listdir() 会抛出 FileNotFoundError 或 NotADirectoryError。尤其在定时任务中,日志目录可能被手动删除或权限变更,脚本不能因此中断。
实操建议:
文心一言
文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。
下载
- 用
os.path.isdir(path)提前校验,不依赖异常捕获做流程控制 - 避免用
os.listdir(".")这类相对路径——定时任务的工作目录不可靠,始终用绝对路径(如/var/log/myapp/) - 过滤掉子目录:对每个
entry调用os.path.isfile(os.path.join(log_dir, entry)),防止误删整个子目录
用 os.path.getmtime() 判断日志是否过期时要注意时区与精度
os.path.getmtime() 返回的是 Unix 时间戳(秒级),但它的值取决于文件系统记录的最后修改时间——而很多日志轮转工具(如 logrotate)会保留原文件 mtime,导致“看似没过期”却实际该删。更稳妥的方式是按文件名中的日期解析(如 app.log.2025-03-15),但若只能依赖 mtime,就得注意两点:
- 不要用
datetime.now() - mtime > 86400 * 7简单比较:datetime.now()默认是本地时区,而 mtime 是 UTC 秒数,跨时区机器上可能偏差整小时 - 统一用
time.time()获取当前时间戳,和os.path.getmtime()类型一致,避免类型转换引入误差 - 考虑文件系统挂载参数(如
noatime不影响 mtime,但某些容器环境可能禁用 mtime 更新)
删除前务必用 os.remove() 而非 shutil.rmtree(),除非明确要删目录
日志文件通常是普通文件,不是目录。如果误把 shutil.rmtree() 用在单个文件上,会报错 OSError: [Errno 20] Not a directory;反过来,若日志目录下混有子目录(比如按日期分的 2025-03/),又只用 os.remove(),则跳过整个子目录,造成清理遗漏。
实操建议:
- 先用
os.path.isfile()判定目标类型,再选os.remove()或shutil.rmtree() - 删除失败时记录具体错误:比如
PermissionError表示权限不足,ProcessLookupError(Windows)或EBUSY(Linux)说明文件正被写入——此时应跳过,而非重试或强制 kill 进程 - 避免用
os.system("rm -f ..."):无法精确捕获错误码,且 shell 注入风险在拼接路径时真实存在
脚本部署后常被忽略的执行上下文问题
本地测试通过的脚本,放到 cron 里就失败,90% 是因为环境差异。Python 解释器路径、PATH、当前工作目录、用户权限、字符编码全部不同。
关键检查点:
- 在 crontab 中显式指定 Python 路径:
/usr/bin/python3 /opt/scripts/clean_logs.py,别用python或python3 - 脚本开头加
#!/usr/bin/env python3并chmod +x不够——cron 默认不读 shell 的.bashrc,PATH 往往只有/usr/bin:/bin - 所有日志路径、配置路径都写绝对路径,不要依赖
__file__拼接(__file__在 symlink 场景下可能指向软链源而非实际位置) - 用
logging.FileHandler记录操作日志时,确保日志目录存在且目标用户有写权限——否则连错误都记不了
真正麻烦的从来不是“怎么删”,而是“删的时候谁在写、删完谁在读、删失败了有没有人知道”。路径、权限、时间判断这三块,漏一个,脚本就从工具变成隐患。