云计算百科
云计算领域专业知识百科平台

服务器系统盘被 syslog 占满的完整排查与解决记录

一、问题背景与现象

我的一台云服务器配置为 4 核 CPU、4G 内存、40G 系统盘,上面跑了一个 Java Spring Boot 应用,用 systemd 做服务管理。某天在云控制台看到「用量与监控」里出现告警:

  • 系统盘使用率 100%,40G 全部用满,可用空间为 0;
  • CPU 使用率 100%;
  • 内存 约 67%;
  • 系统盘 IO 写入约 5MB/s,持续较高。

应用访问明显变慢,甚至出现超时。当时不能更换或升级服务器,只能从现有环境上排查并彻底解决。


二、第一步:定位是谁占满了磁盘

我首先在服务器上执行了下面命令,看根分区和各目录占用:

df -h /
du -sh /* 2>/dev/null

结果: 根分区 /dev/vda2 显示 40G 已用满,可用 0。在 du -sh /* 的输出里,/var 目录占用了约 33G,其它如 /usr、/opt 等都只有几 G 或更少。可以确定问题在 /var。

接着进入 /var 继续往下看:

cd /var
du -sh * 2>/dev/null

结果: /var/log 占约 32G,其余如 lib、cache 等都很小。说明是系统日志目录在占空间。

再进到 /var/log 看具体是哪些文件:

cd /var/log
du -sh * 2>/dev/null

结果:

  • syslog:约 11G;
  • syslog.1:约 21G;
  • journal:约 938M;
  • 其它如 auth.log、btmp、mysql 等都在几十 M 或更小。

结论:系统盘被占满的直接原因,就是 /var/log/syslog 和 syslog.1 这两个文件,合计约 32G。


三、第二步:立刻释放空间(清空 syslog)

在查原因的同时,必须先腾出空间,否则很多操作都会失败。我做了以下操作:

# 1. 清空当前 syslog(保留文件,便于 rsyslog 继续写)
sudo truncate -s 0 /var/log/syslog

# 2. 删除已轮转的大文件 syslog.1
sudo rm /var/log/syslog.1

# 3. 删除所有 syslog 轮转备份和压缩包(按需可先备份)
sudo rm -f /var/log/syslog.*
sudo rm -f /var/log/syslog.*.gz

# 4. 确认空间
df -h /

结果: df -h / 显示系统盘从「40G 满」变为 已用约 7G,可用约 31G,使用率约 19%。空间立刻释放,可以继续做后续配置。
在这里插入图片描述


四、第三步:弄清 syslog 为什么会长这么大

我查了资料并对照自己的部署方式,理清了整条链路:

  • 应用:Java 应用(Spring Boot)的日志通过 Logback 输出到了控制台(stdout/stderr),即 CONSOLE appender 一直在用。
  • systemd:应用是用 systemd 管理的,service 文件里配置了 StandardOutput=journal 和 StandardError=journal,所以进程的所有标准输出、标准错误都会被 systemd 收到并写入 journal。
  • rsyslog:在 Ubuntu 上,rsyslog 会从 journal 读取这些内容,并写入 /var/log/syslog。
  • logrotate:默认的 rsyslog 轮转配置多是按天轮转,没有按文件大小做严格限制。应用日志量一大,syslog 就会一直增长,直到把 40G 系统盘写满。
  • 所以,根本原因是:应用的控制台日志 → systemd journal → rsyslog → syslog,且 syslog 没有按大小轮转。要彻底解决,需要两件事:一是限制 syslog 大小并轮转;二是从源头减少写入(不让应用输出再进 journal/syslog)。


    五、第四步:修改 systemd 服务,不再把应用输出写入 journal

    我先改的是 systemd,这样无需重新打包应用就能立刻减少 syslog 的增长。

    编辑服务文件(你的实际服务名和路径请自行替换):

    sudo nano /etc/systemd/system/你的服务名.service

    把其中的:

    StandardOutput=journal
    StandardError=journal

    改成:

    StandardOutput=null
    StandardError=null

    保存后执行:

    sudo systemctl daemon-reload
    sudo systemctl restart 你的服务名
    sudo systemctl status 你的服务名

    结果: status 显示服务为 active (running),应用正常。之后应用的 stdout/stderr 不再进入 journal,也就不会再灌进 syslog,这一步立即生效。


    六、第五步:配置 logrotate,让 syslog 按大小轮转(踩坑记录)

    为了防止以后其它程序或残留日志再把 syslog 写大,需要让 syslog 按大小轮转,例如超过 50M 就轮转,最多保留 3 份。我编辑了 rsyslog 的 logrotate 配置:

    sudo nano /etc/logrotate.d/rsyslog

    第一次我写成了这样(错误示范):在 /var/log/syslog 的配置块里加了 su syslog adm,并加了 size 50M、rotate 3 等。然后执行:

    sudo logrotate -f /etc/logrotate.d/rsyslog

    结果: 报错 “parent directory has insecure permissions”,并且报 “failed to rename /var/log/syslog to /var/log/syslog.1: Permission denied”。原因是:使用 su syslog adm 时,logrotate 会以 syslog 用户身份去轮转,而 /var/log 目录一般是 root 拥有、755 权限,syslog 用户没有权限在下面重命名或创建文件,所以会 Permission denied;同时系统认为 /var/log 的权限「不安全」,要求设置 su,形成矛盾。

    正确做法: 先修正 /var/log 的权限,再去掉所有 su syslog adm,让 logrotate 以 root 身份执行轮转。我执行了:

    sudo chmod 755 /var/log
    sudo chown root:root /var/log

    然后再次编辑 /etc/logrotate.d/rsyslog,删掉第一段里 syslog 的 su syslog adm,只保留 size、rotate、postrotate 等,保存后再执行:

    sudo logrotate -f /etc/logrotate.d/rsyslog

    结果: 又报了 “error creating output file /var/log/auth.log.1.gz: Permission denied”。原因是第二段(mail、daemon、kern、auth 等一堆日志)里我还留着 su syslog adm,同样导致以 syslog 身份在 /var/log 下创建 .gz 文件时权限不足。

    于是我再次打开配置,把第二段里的 su syslog adm 也删掉,让两段都由 root 来轮转。最终两段配置大致如下(仅作参考,以你系统实际为准):

    第一段:/var/log/syslog

    /var/log/syslog
    {
    rotate 3
    size 50M
    missingok
    notifempty
    delaycompress
    compress
    postrotate
    /usr/lib/rsyslog/rsyslog-rotate
    endscript
    }

    第二段:其它系统日志(不再包含 su syslog adm)

    /var/log/mail.info
    /var/log/mail.warn
    …(略)
    /var/log/messages
    {
    rotate 4
    weekly
    missingok
    notifempty
    compress
    delaycompress
    sharedscripts
    postrotate
    /usr/lib/rsyslog/rsyslog-rotate
    endscript
    }

    保存后再次执行:

    sudo logrotate -f /etc/logrotate.d/rsyslog

    结果: 这次没有任何报错,命令正常结束。说明 logrotate 已能成功轮转 syslog 及其它日志,之后 syslog 超过 50M 会自动轮转,最多保留 3 份,不会再无限增长占满磁盘。


    七、第六步:验证与收尾检查

    我做了几项检查,确认整体状态正常:

    1. 确认 logrotate 定时任务存在

    ls /etc/cron.daily/logrotate
    systemctl status logrotate.timer

    在这里插入图片描述

    结果: 文件存在,timer 为 active (waiting),下次触发时间为次日 00:00,说明每天会自动执行一次 logrotate。

    2. 查看磁盘与 syslog

    df -h /
    ls -lh /var/log/syslog

    结果: 磁盘显示已用约 6.9G,可用约 31G,使用率约 19%。ls -lh /var/log/syslog 提示 No such file or directory,这是因为刚才执行 logrotate 时已经把当时的 syslog 轮转成了 syslog.1 等,新的 syslog 要等 rsyslog 下次写入时才会创建,属于正常现象。若想立刻看到文件,可以执行 sudo systemctl restart rsyslog 让 rsyslog 重新打开日志文件。

    3. 应用与日志链路

    应用已通过 systemd 改为 StandardOutput=null / StandardError=null,不再向 syslog 写应用日志;syslog 已通过 logrotate 限制为单文件 50M、保留 3 份。从「应用控制台 → journal → syslog」这条链路已经被切断,且 syslog 自身也不会再无限增长。


    八、我在应用侧做的补充优化(可选参考)

    除了上述服务器和 systemd 上的操作,我在应用项目里也做了两点配置,进一步减少日志对磁盘和 IO 的影响:

    1. Logback:默认不输出到控制台

    把「是否写控制台」从「只有 prod 才不写」改成了「只有 dev 才写」:即默认(不设 profile)或生产环境时,root 和业务 logger 都不挂 CONSOLE appender,只写文件,并设置了 totalSizeCap、maxHistory 等限制;只有显式加 spring.profiles.active=dev 时才写控制台。这样在服务器上不设 profile 时,应用本身也不会再往 stdout 打日志,双重保险。

    2. application.properties 与生产对齐

    在共用的 application.properties 里把日志级别改为 WARN、定时任务线程池调小、日志清理保留天数缩短等,和之前生产环境配置保持一致,减少日志量和 CPU 占用。这样无论是否单独启用 prod profile,服务器上的行为都更可控。

    这两部分属于「应用层优化」,不影响前面「清空 syslog + 改 systemd + 配 logrotate」的主线操作;若你暂时不想改应用,只做服务器和 systemd 部分也能解决 syslog 占满的问题。


    九、整体结果小结

    阶段我做的操作结果
    定位 df、du 从根目录查到 /var/log,再查到 syslog/syslog.1 确认 syslog 占约 32G,是占满根因
    释放空间 truncate 清空 syslog,删除 syslog.1 及 .gz 可用空间从 0 恢复到约 31G
    切断来源 systemd 服务中 StandardOutput/Error 改为 null 应用输出不再进 journal/syslog
    限制 syslog 修正 /var/log 权限,去掉 logrotate 中两处 su,配置 size 50M、rotate 3 logrotate 执行成功,syslog 不再无限增长
    验证 查看 df、logrotate.timer、cron.daily 磁盘 19%,定时轮转正常

    最终在不换机、不扩容的前提下,解决了系统盘被 syslog 占满的问题,并避免了复发。若你也是 Java/Spring Boot + systemd 部署,遇到类似「系统盘 100%、/var/log 巨大」的情况,可以按上述顺序:先查 du 定位到 syslog,再清空释放空间,改 systemd 关掉 journal 输出,最后用 logrotate 做大小轮转并注意权限与 su 的坑。


    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 服务器系统盘被 syslog 占满的完整排查与解决记录
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!