手把手写一个定时清理旧日志的 Python 小脚本:先演练再删除,误删能找回

举报
yd_283275723 发表于 2026/10/28 20:51:22 2026/10/28
【摘要】 服务器旧日志越积越多,直接删又怕删错。这篇用一个不用装第三方库的 Python 小脚本,带你先演练、再移到回收站、观察几天最后清空,附定时任务的挂法和几个容易踩的坑。

大家是不是都遇到过这种情况:服务器跑着跑着,磁盘突然就满了,一查,好多都是几个月前的旧日志。直接 rm 一把梭吧,心里又发虚,万一删错了正在用的文件,或者删掉了还没排查完的问题日志,那就麻烦了。

今天分享一个我自己常用的稳妥做法:先用 Python 写个小脚本,只列出、只演练,不直接删;确认没问题了,再真正清理;而且清理前先把文件移到一个回收站目录,留几天缓冲期,误删了还能找回来。整个过程不用装任何第三方库,系统自带 Python 就能跑。

先说思路,别一上来就删

我的原则就三条:

  1. 只动自己明确指定的目录,比如 /var/log/myapp 这种应用日志目录,别对着 /var/log 整目录开刀。
  2. 按修改时间判断,默认只处理 30 天前的文件,天数用参数传,写死在代码里容易手滑。
  3. 删除分两步:先移到回收站目录,过几天确认没问题,再清空回收站。

这样哪怕规则写错了,第一步也只是挪了个地方,不是直接没了。

第一步:准备一个测试目录

先别在真实日志目录上试。在自己家目录下建个演练场,里面放几个文件,再把其中几个文件的修改时间改旧一点,用来模拟旧日志:

mkdir -p ~/log-clean-test ~/log-clean-test/trash
cd ~/log-clean-test
touch app-2026-01.log app-2026-02.log app-new.log
touch -d '40 days ago' app-2026-01.log
touch -d '35 days ago' app-2026-02.log
ls -l --time-style=long-iso

这一步的意思很简单:先看清楚,哪些文件会被判定为旧文件,哪些不会。app-new.log 是刚建的,按 30 天的规则就不该被动。

第二步:写脚本,先演练

新建一个文件,名字就叫 clean_old_logs.py,内容如下:

import argparse
import shutil
from datetime import datetime, timedelta
from pathlib import Path


def main():
    parser = argparse.ArgumentParser(description='清理旧日志:先演练,再移动到回收站')
    parser.add_argument('log_dir', help='日志目录,例如 ~/log-clean-test')
    parser.add_argument('trash_dir', help='回收站目录,例如 ~/log-clean-test/trash')
    parser.add_argument('--days', type=int, default=30, help='超过多少天算旧文件,默认 30')
    parser.add_argument('--apply', action='store_true', help='不加这个参数时只演练、不移动文件')
    args = parser.parse_args()

    log_dir = Path(args.log_dir).expanduser()
    trash_dir = Path(args.trash_dir).expanduser()
    cutoff = datetime.now() - timedelta(days=args.days)

    if not log_dir.is_dir():
        print(f'目录不存在:{log_dir}')
        return

    candidates = []
    for item in log_dir.iterdir():
        if not item.is_file():
            continue
        mtime = datetime.fromtimestamp(item.stat().st_mtime)
        if mtime < cutoff:
            candidates.append((item, mtime))

    if not candidates:
        print('没有符合条件的旧文件,什么都不做。')
        return

    print(f'判定标准:修改时间早于 {cutoff:%Y-%m-%d %H:%M} 的文件')
    for item, mtime in sorted(candidates):
        print(f'  {item.name}  修改时间 {mtime:%Y-%m-%d %H:%M}')

    if not args.apply:
        print('演练模式:上面这些文件只是被列出来,没有被移动。确认无误后,再加 --apply 真正执行。')
        return

    trash_dir.mkdir(parents=True, exist_ok=True)
    for item, _mtime in candidates:
        target = trash_dir / item.name
        if target.exists():
            target = trash_dir / f"{item.stem}-dup{item.suffix}"
        shutil.move(str(item), str(target))
        print(f'已移到回收站:{item.name} -> {target}')
    print('完成。先别急着清空回收站,观察几天再说。')


if __name__ == '__main__':
    main()

这里有几个新手容易忽略的小细节,顺手说一下:

  • 只处理 log_dir 下一层的文件,不递归进子目录,避免一不小心把子目录里的东西也算进去。
  • 回收站里如果已经有同名文件,会改成 -dup 后缀,不会直接覆盖。
  • 没有 --apply 的时候,脚本只打印、不动文件,这个设计就是专门防手滑的。

第三步:先演练,再执行

先跑演练模式:

python3 clean_old_logs.py ~/log-clean-test ~/log-clean-test/trash --days 30

这时候你应该只看到 app-2026-01.log 和 app-2026-02.log 被列出来,app-new.log 不在名单里。如果名单里出现了你不认识、或者不该动的文件,马上停下来,检查一下目录是不是写错了,或者天数是不是设错了。

名单确认没问题了,再加 --apply 真正执行:

python3 clean_old_logs.py ~/log-clean-test ~/log-clean-test/trash --days 30 --apply

执行完再看一眼:原目录里应该只剩 app-new.log,回收站里多了两个旧文件。这时候先别清空回收站。

第四步:观察几天,再清空回收站

我的习惯是,回收站里的东西至少留 3 到 7 天。这几天里如果应用跑着没问题,也没人来找旧日志排查问题,再清空回收站:

ls ~/log-clean-test/trash
rm ~/log-clean-test/trash/*.log

如果这几天发现删错了,直接从回收站把文件移回去就行:

mv ~/log-clean-test/trash/app-2026-01.log ~/log-clean-test/

这就是两步删除的好处:第一步错了还能补救,第二步才是真的扔掉。

想定时跑,怎么挂上去

确认脚本在测试目录跑没问题之后,再考虑定时。先在真实目录上也走一遍演练模式,名单确认无误,再用 crontab 定时跑。举个例子,每天凌晨 2 点跑一次,日志目录和回收站目录换成你自己的真实路径:

crontab -e

加上一行:

0 2 * * * /usr/bin/python3 /home/你的用户名/clean_old_logs.py /var/log/myapp /var/log/myapp-trash --days 30 --apply >> /home/你的用户名/clean-logs.log 2>&1

注意两点:第一,crontab 里的路径要写绝对路径,别写 ~/,定时任务的环境和你手动登录的环境不完全一样;第二,刚开始挂定时任务的时候,建议先把 --apply 去掉跑几天,只看日志里列出来的名单,确认每天的名单都合理,再改成真正执行。

几个容易踩的坑

  • 千万别把日志目录写成 / 或者 /var/log 这种大目录,也别用通配符 rm -rf 拼路径,脚本里只认你传进来的那一个目录,相对安全。
  • 正在被程序写着的日志文件,移动之后程序可能还在往旧的文件句柄里写,表现就是新文件没内容、旧文件还在变大。遇到这种情况,先让应用按自己的方式轮转日志,或者重启一下应用,别硬删。
  • 磁盘满了先别慌着删,先用 du 看看是哪一级目录占得多,再决定动哪里。日志只是最常见的一种,数据库、备份、临时文件也都可能是大头。
  • 回收站本身也要定期清空,不然回收站就成了新的磁盘杀手,等于白清理。

总结一下

一句话:清理旧日志,别图快,先演练、再挪到回收站、观察几天、最后清空。脚本本身很短,关键是这个流程。等你把这套流程跑顺了,以后再接手别人的服务器,看到磁盘告警也不会手忙脚乱了。

本文没有配截图,因为步骤本身就是按命令一步步来的,照着敲一遍,比看截图更清楚。建议先在测试目录完整跑一遍,再用到真实目录上。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。