一、先说下这个坑是咋回事

很多用Automation360的朋友,可能都有过这种经历:某天突然发现服务器磁盘满了,系统跑不动了,一查发现是日志文件占了几个G甚至几十个G。为啥呢?十有八九是日志级别设置不对。

日志这个东西吧,就像家里产生的垃圾。平时做饭剩菜、包装盒啥的,随手扔进垃圾桶,一天也就一袋。但如果你把垃圾桶设置成“只进不出”,或者把每个人每天产生的垃圾量放大十倍,那家里很快就堆满。

Automation360的日志也是一样。它本身会记录机器人运行的各种信息,级别有简单有详细。如果选了那种最详细的级别,它会把每一步操作的细节、每个变量的值、每条网络的请求都记下来。刚开始你可能觉得没啥,但几天下来,文件大得吓人。

举个例子,假设我们用Python写一个小工具来模拟日志级别对文件大小的影响。先定义一个日志级别对应的“啰嗦程度”:

# 技术栈:Python
# 模拟不同日志级别的冗余系数
level_verbose = {
    "ERROR": 1,      # 只记录错误,量最少
    "WARN": 5,       # 警告多一些
    "INFO": 10,      # 常规信息
    "DEBUG": 50,     # 调试信息非常细
    "TRACE": 100     # 追踪级别,几乎每行代码都记
}

# 假设每天产生的基础日志量为100MB(ERROR级别之下)
base_size_mb = 100
for level, factor in level_verbose.items():
    # 计算该级别下每天预计产生的日志大小
    daily_size = base_size_mb * factor
    print(f"{level}: 每天约 {daily_size} MB")

运行这个脚本,你会看到ERROR级别100MB,DEBUG要5GB,TRACE要10GB。这还只是一天,连续跑一个星期,磁盘再大也顶不住。

当然,Automation360本身有日志级别设置的地方,比如在配置文件里。很多人为了排查问题,随手选成DEBUG甚至TRACE,结果故障没找到,先把磁盘塞满了。

二、日志级别和磁盘爆满的关系

日志级别不是越高越好,也不是越低越省事。它是个权衡。错误级别(ERROR)只记录出错的地方,信息很稀薄,但可能会漏掉一些线索。调试级别(DEBUG)会把详细的过程都写下来,排查问题时很好用,但代价就是大量写入磁盘。

Automation360基于Java生态,它的日志体系很像log4j或者slf4j那套东西。常用的级别从低到高大致是:TRACE < DEBUG < INFO < WARN < ERROR。级别设置得越低,记录的内容越多,磁盘占用越大。这就像你的手机开了后台自启动,每个应用都在不停更新,流量和电量都受不了。

我们再用Python的logging库模拟一下,看看不同级别实际输出日志的差别:

# 技术栈:Python
import logging

# 配置日志输出到控制台,方便观察
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger("example")

# 下面五条日志在不同的级别下会出现不同的情况
logger.trace("这是追踪级别,非常详细")
logger.debug("这是调试级别,有一个变量值:42")
logger.info("这是信息级别,操作已完成")
logger.warning("这是警告级别,内存即将不足")
logger.error("这是错误级别,任务失败")

注意,并不是所有Python版本都自带trace级别,这里只是为了演示。实际跑的时候,如果你的日志级别设成ERROR,那么DEBUG和INFO不会输出,文件里的内容就很少;如果设成DEBUG,上面所有这些都会写到日志里。次数一多,差异立刻显现。

所以,在Automation360里,生产环境一般建议用INFO,只有在临时排查问题时用DEBUG,查完马上改回去。用TRACE那是非常极端的情况,比如在做深入的内核级分析,否则千万不要长期开启。

三、预警方案:提前发现磁盘快满

别等磁盘爆满才去救火,我们应该在它还没满的时候就提前发现苗头。这里有两个办法:一是看Automation360自己的监控面板,二是我们写一个脚本来定时扫描日志目录大小。后者更灵活,也更适合自动化。

3.1 用Python脚本检查日志目录大小

我们可以让机器人每天晚上自动跑一个检查脚本,或者用系统的定时任务去执行。脚本的逻辑很简单:计算指定日志目录的总大小,和阈值比较,如果超过阈值就发个警告日志,或者直接调API发通知。

下面这个脚本就是干这个事的:

# 技术栈:Python
import os

def get_dir_size(path):
    """
    递归计算目录下所有文件的总大小
    :param path: 目录路径
    :return: 总字节数
    """
    total = 0
    # 遍历目录下的所有文件和子目录
    for entry in os.scandir(path):
        if entry.is_file():
            # 如果是文件,直接把文件大小加上
            total += entry.stat().st_size
        elif entry.is_dir():
            # 如果是子目录,递归计算
            total += get_dir_size(entry.path)
    return total

# 配置日志目录和告警阈值(单位:字节)
log_path = "C:\\Automation360\\Logs"  # 改成你的实际路径
warn_threshold = 10 * 1024 * 1024 * 1024  # 10GB

# 先判断目录是否存在
if not os.path.isdir(log_path):
    print("日志目录不存在,请检查路径")
else:
    size_bytes = get_dir_size(log_path)
    size_gb = size_bytes / (1024 ** 3)
    print(f"当前日志总大小:{size_gb:.2f} GB")

    # 超过阈值就告警
    if size_bytes > warn_threshold:
        print(f"警告:日志已超过 {warn_threshold / (1024**3):.0f} GB,请立即处理!")
    else:
        print("日志大小正常,继续观察。")

这个脚本的注释已经写得比较清楚了。你可以把它保存成check_log_size.py,然后在系统里设置每天凌晨跑一次。如果有一天它突然打了“警告”,说明磁盘快扛不住了,你就有时间去清理。

3.2 用系统定时任务调用这个脚本

Windows下可以用“任务计划程序”,Linux下可以用crontab。这里不展开讲系统命令了,因为你只需要把这个Python脚本挂在任务计划里,让它每天执行,把打印的信息重定向到一个文本文件或者发邮件。如果只是给自己看,直接看控制台输出也行。

另外,这里有个小技巧:你可以把阈值设成磁盘总容量的80%,这样预警会更早。

四、清理方案:给磁盘瘦身

预警只是第一步,真正要做的是清理。清理日志要注意别把正在跑的机器人日志删了,最好按时间或大小来做。

4.1 按时间清理:只保留最近N天的日志

Automation360的日志文件一般会按日期或者小时生成名字,比如Automation-2025-03-01.log。我们只需要扫描日志目录,凡是文件名里带日期且日期早于某个时间点的,就把它删掉。

下面这个Python脚本会删除目录下所有修改时间超过7天的文件:

# 技术栈:Python
import os
import time
from datetime import datetime, timedelta

def clean_old_logs(log_dir, days_to_keep):
    """
    删除指定目录下超过保留天数的日志文件
    :param log_dir: 日志目录
    :param days_to_keep: 保留最近几天的日志
    """
    # 计算截止时间戳(当前时间 - 保留天数)
    deadline = time.time() - days_to_keep * 86400
    removed_count = 0
    freed_bytes = 0

    for filename in os.listdir(log_dir):
        file_path = os.path.join(log_dir, filename)
        # 只处理文件,不处理子目录
        if os.path.isfile(file_path):
            # 获取文件的修改时间
            mtime = os.path.getmtime(file_path)
            if mtime < deadline:
                size = os.path.getsize(file_path)
                try:
                    os.remove(file_path)
                    removed_count += 1
                    freed_bytes += size
                    print(f"已删除:{filename}({size/1024:.1f}KB)")
                except Exception as e:
                    print(f"删除失败:{filename},原因:{e}")

    print(f"共删除 {removed_count} 个文件,释放 {freed_bytes / (1024*1024):.2f} MB")

# 使用示例:清理C:\\Automation360\\Logs下超过7天的日志
clean_old_logs("C:\\Automation360\\Logs", days_to_keep=7)

这个脚本比较温和,只删修改时间早于7天的文件。你可以在正式使用前先跑一遍,看看它会删哪些文件,确认没问题再真的执行。为了避免误删,还可以加一个白名单,比如保留error开头的文件。

4.2 按大小清理:日志太大就压缩或删除

如果你不想设置“保留多少天”,也可以设置“最多允许占多少空间”。比如日志目录超过10GB,就把最老的文件删掉,直到总大小低于5GB。

这个清理策略用Python实现也不难:

# 技术栈:Python
import os
from pathlib import Path

def clean_by_size(log_dir, max_size_gb, target_size_gb):
    """
    当日志目录超过max_size_gb时,按照文件修改时间从早到晚删除,
    直到目录总大小低于target_size_gb
    :param log_dir: 日志目录
    :param max_size_gb: 触发清理的阈值
    :param target_size_gb: 清理后希望达到的大小
    """
    max_bytes = max_size_gb * 1024 ** 3
    target_bytes = target_size_gb * 1024 ** 3

    # 获取目录下所有文件的信息(路径、大小、修改时间)
    files = []
    for item in Path(log_dir).iterdir():
        if item.is_file():
            files.append({
                "path": item,
                "size": item.stat().st_size,
                "mtime": item.stat().st_mtime,
            })

    # 计算当前总大小
    total = sum(f["size"] for f in files)
    print(f"当前日志总大小:{total / (1024**3):.2f} GB")

    # 如果没超过阈值,就不做任何事
    if total <= max_bytes:
        print("日志没有超过阈值,不用清理。")
        return

    # 按修改时间排序(老的在前)
    files.sort(key=lambda f: f["mtime"])

    # 从最老的文件开始删,直到低于目标大小
    freed = 0
    removed_count = 0
    for f in files:
        if total - freed <= target_bytes:
            break
        try:
            f["path"].unlink()  # 删除文件
            freed += f["size"]
            removed_count += 1
            print(f"删除:{f['path'].name}")
        except Exception as e:
            print(f"删除失败:{f['path'].name},原因:{e}")

    print(f"共删除 {removed_count} 个文件,释放 {freed / (1024**3):.2f} GB")
    print(f"当前日志总大小:{(total - freed) / (1024**3):.2f} GB")

# 调用示例:日志目录超过10GB时启动清理,直到低于5GB
clean_by_size("C:\\Automation360\\Logs", max_size_gb=10, target_size_gb=5)

这个策略的好处是磁盘空间可控,不会因为日志太多而爆满。缺点是可能把最近几天的日志也删掉(如果这几天日志特别大),所以使用时建议把target_size_gb设置得大一些,或者同时结合时间条件。

4.3 先压缩再删除:给日志留个全尸

有些日志可能有审计或者归档需求,一下子删了不合适。那我们可以先把超过期限的.log文件压缩成.zip.gz,然后把原始log删掉。这样既释放了空间,又保留了证据。

用Python的zipfile模块可以实现压缩:

# 技术栈:Python
import os
import zipfile
from datetime import datetime

def archive_old_logs(log_dir, days_old=30):
    """
    将超过指定天数的.log文件打包成zip,然后删除原文件
    :param log_dir: 日志目录
    :param days_old: 超过多少天的文件需要归档
    """
    now = datetime.now()
    archive_name = os.path.join(log_dir, f"archive_{now.strftime('%Y%m%d')}.zip")

    # 创建zip文件(追加模式,如果存在)
    with zipfile.ZipFile(archive_name, 'a', zipfile.ZIP_DEFLATED) as zf:
        for filename in os.listdir(log_dir):
            file_path = os.path.join(log_dir, filename)
            if not os.path.isfile(file_path):
                continue
            # 只处理.log后缀
            if not filename.endswith('.log'):
                continue
            # 获取文件修改时间,判断是否超过days_old天
            mtime = datetime.fromtimestamp(os.path.getmtime(file_path))
            if (now - mtime).days > days_old:
                # 把文件写入zip包中,使用相对路径
                zf.write(file_path, arcname=filename)
                # 写入完成后删除原文件
                os.remove(file_path)
                print(f"已归档并删除:{filename}")

    print("归档完成,压缩包位置:", archive_name)

# 调用示例:将日志目录下超过30天的.log文件归档
archive_old_logs("C:\\Automation360\\Logs", days_old=30)

用了这个脚本,日志会越来越少,但zip包会慢慢变大。建议定期把zip包转移到其他存储或者云上去,不要一直占着本地空间。

五、需要注意的几个坑

清理日志看着简单,实操起来有很多细节要注意。我踩过几个坑,给大家分享一下。

第一,别在机器人正在运行的时候暴力删日志。有些日志文件被进程占用,删不掉或者删了之后会导致程序写文件出错。最好在机器人服务停止时执行清理,或者至少避开业务高峰期。

第二,删日志前一定要确认路径。别把目录写错,把重要数据删了。建议在脚本里加一个参数,比如--dry-run,先只列出要删的文件名,不打真的删。确认无误后再去掉--dry-run执行。

第三,日志级别要记得“用完还原”。很多人排查完问题,忘了把DEBUG改回INFO,结果日志继续暴涨。最好在日志级别配置里加一个注释,或者在代码里设置一个开关,只能临时开启DEBUG,比如持续8小时自动切回INFO。

第四,如果Automation360跑在云服务器上,磁盘空间可能分区分得比较细。除了日志,其他地方也会占空间。所以预警脚本最好检查整个磁盘的剩余空间,而不只是日志目录。

六、文章总结

Automation360日志级别设置不当导致磁盘爆满的问题,本质上是一个“日志量失控”的问题。解决思路并不复杂:一是控制源头,平时用合理的日志级别;二是做好监控,提前发现暴涨苗头;三是建立清理机制,让日志自动保持在一个安全的体积范围内。

我们用了Python写了几个实用的小工具来演示如何检查日志目录大小、按时间清理、按大小清理、以及归档压缩。你完全可以把这些脚本放进定时任务,让它们每天自动执行。这样磁盘空间基本就稳了。

最后想提醒一句:日志是程序的“病历卡”,它本身没有错,错的是我们没有管理好它。别等磁盘爆满才后悔,从现在起,把日志级别调低一点,把清理脚本安排上,你的服务器就能一直健健康康地跑下去。