Linux日志过大占满磁盘,logrotate日志切割配置

前言

网站跑久了,Nginx、MySQL、PHP-FPM的日志几个G地涨,df -h一看磁盘被日志占满,服务直接报错。手动删不是长久之计,logrotate 是Linux自带的日志切割工具,按天/按大小自动切分并保留指定份数,配一次永久省心。

一、logrotate工作原理

logrotate本身靠系统定时任务(/etc/cron.daily/logrotate)每天跑一次,读取配置:

  • 全局配置:/etc/logrotate.conf
  • 自定义配置目录:/etc/logrotate.d/
    我们一般在 /etc/logrotate.d/ 下为某个服务单独写配置。

二、以Nginx日志为例配置

新建 /etc/logrotate.d/nginx:

/var/log/nginx/*.log {
    daily                 # 按天切割
    missingok             # 日志不存在不报错
    rotate 14             # 保留14份历史
    compress              # 切割后gzip压缩
    delaycompress         # 延迟一次再压缩,避免影响正在写的文件
    notifempty            # 空日志不切割
    create 0644 nginx nginx  # 新建日志文件属主权限
    sharedscripts         # 多个日志只执行一次postrotate
    postrotate
        if [ -f /run/nginx.pid ]; then
            kill -USR1 `cat /run/nginx.pid`
        fi
    endscript
}

关键点:切割后要给Nginx发USR1信号,让它重新打开日志文件,否则还会往旧文件写。

三、按大小切割(不限时间)

如果日志涨得快,按大小更合理:

/var/log/nginx/error.log {
    size 100M            # 超过100M切
    rotate 10
    compress
    missingok
    notifempty
    create 0644 nginx nginx
    postrotate
        kill -USR1 `cat /run/nginx.pid`
    endscript
}

四、测试与立即执行

不等到定时,手动试运行(调试用 -d 打印过程不真正执行):

# 调试,看会做什么
logrotate -d /etc/logrotate.d/nginx
# 强制立即切割一次
logrotate -f /etc/logrotate.d/nginx

切割后原日志变成 xxx.log-20261021,隔天再压成 .gz。

五、常见坑

  1. 切割后服务还往旧文件写:缺postrotate里的 kill -USR1,或pid路径写错,导致旧文件越来越大;
  2. 直接rm删正在写的日志:空间没释放,要 > 文件 清空或重启服务;
  3. compress和delaycompress一起用仍报错:第一次切出的文件先不压,第二次才压,别误以为没生效;
  4. 日志目录属主不对:create指定的用户组要真实存在,否则新建文件失败;
  5. cron没跑:确认 crond 服务开机自启,否则logrotate永远不触发。

总结

在 /etc/logrotate.d/ 为每个大日志写一份切割规则,配好daily/size、rotate份数和postrotate信号重开日志,logrotate -f 验证一次,磁盘就不会再被单个日志吃满。

遇到问题加QQ23979811 协助处理


emer 发布于  2026-10-21 07:22 

Linux磁盘满了怎么清理,大文件查找命令

前言

网站突然打不开了?SSH连不上了?一查磁盘100%满了!本文讲怎么查找大文件、清理磁盘空间。

一、查看磁盘使用情况

df命令

df -h

输出:

Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        40G   38G  2.0G  95% /

看什么:

  • Use%:使用率,超过90%就要注意了
  • Avail:可用空间

查看当前目录占用

du -sh

二、查找大文件

查找大于100M的文件

find / -type f -size +100M 2>/dev/null

解释:

  • /:从根目录开始找
  • -type f:只找文件
  • -size +100M:大于100M
  • 2>/dev/null:忽略错误信息

查找大于1G的文件

find / -type f -size +1G 2>/dev/null

按大小排序

find / -type f -size +100M 2>/dev/null | xargs du -h | sort -rh

三、查找大目录

查看各目录大小

du -sh /*

一级一级往下找

du -sh /var/*
du -sh /var/log/*
du -sh /var/lib/*

查看前10大目录

du -sh /* | sort -rh | head -10

四、常见大文件位置

1. 日志文件

/var/log/
/var/log/messages
/var/log/nginx/
/var/log/mysql/

2. 临时文件

/tmp/
/var/tmp/

3. 邮件

/var/spool/mail/

4. 数据库文件

/var/lib/mysql/

5. Docker镜像

/var/lib/docker/

6. 上传文件

/www/wwwroot/
/var/www/html/

五、清理方法

清理日志文件

方法1:清空文件

> /var/log/messages

方法2:删除旧日志

find /var/log -name "*.log" -mtime +30 -delete

删除30天前的日志。

清理yum缓存

yum clean all

清理Docker

docker system prune -a

清理临时文件

rm -rf /tmp/*

注意: 正在用的文件别删。

清理旧内核

package-cleanup --oldkernels --count=1

六、查看文件被谁占用

问题: 删了文件但磁盘没释放?

原因: 有进程还在写这个文件。

查看被删除但还被占用的文件

lsof | grep deleted

重启相关进程

systemctl restart nginx

七、常见坑

坑1:删了文件但空间没释放

原因: 进程还在写这个文件。

解决: 重启进程,或者用> 文件名清空。

坑2:日志一直涨

解决: 配置logrotate日志切割。

坑3:Docker占了很多空间

docker system df

清理:

docker system prune -a

八、自动清理脚本

写个脚本定期清理:

#!/bin/bash
# 清理30天前的日志
find /var/log -name "*.log" -mtime +30 -delete
# 清理yum缓存
yum clean all
# 清理Docker
docker system prune -f

加到crontab:

0 3 * * * /bin/bash /root/clean.sh

总结

记住:

  1. 用df -h看磁盘使用率
  2. 用du -sh /*看哪个目录大
  3. 用find / -size +100M找大文件
  4. 先看日志,再看Docker,再看临时文件
  5. 删文件前确认不用了
  6. 删了没释放就重启进程

最常用:

df -h
du -sh /*
find / -type f -size +100M 2>/dev/null

遇到问题加QQ23979811 协助处理


emer 发布于  2026-10-9 07:52 

Docker镜像占用空间过大,清理无用镜像容器

前言

用了一段时间Docker,磁盘满了。docker images一看,一堆旧镜像和停止的容器占着空间。本文讲怎么清理Docker空间。

一、查看Docker占用空间

docker system df

输出:

TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          50        10        15GB      10GB
Containers      30        10        500MB     400MB
Local Volumes   20        5         2GB       1.5GB

RECLAIMABLE 就是可以回收的空间。

二、查看镜像列表

docker images

看REPOSITORY、TAG、SIZE列。

三、清理停止的容器

删除单个容器

docker rm 容器ID/容器名

删除所有停止的容器

docker container prune

会提示确认,输入y。

加-f强制删除

docker container prune -f

不提示直接删。

四、清理无用镜像

删除单个镜像

docker rmi 镜像ID/镜像名

删除所有悬空镜像

悬空镜像就是 <none>:<none> 那些,构建中间产生的。

docker image prune

删除所有未被使用的镜像

docker image prune -a

注意:这会删掉所有没被容器用着的镜像,小心。

五、清理无用卷

查看卷

docker volume ls

删除无用卷

docker volume prune

六、清理无用网络

docker network prune

七、一键全部清理

docker system prune

清理:

  • 停止的容器
  • 无用网络
  • 悬空镜像
  • 构建缓存

连镜像一起删

docker system prune -a

把没被用的镜像也删掉。

加时间过滤

只删24小时前的:

docker system prune -a --filter "until=24h"

八、常见清理场景

场景1:磁盘快满了

# 先看占了多少
docker system df

# 清理停止的容器
docker container prune -f

# 清理悬空镜像
docker image prune -f

# 清理无用卷
docker volume prune -f

场景2:想彻底清理

docker system prune -a -f --volumes

九、手动清理某个镜像

找到镜像ID

docker images

删除

docker rmi 镜像ID

强制删除

如果镜像被停止的容器引用了,先删容器:

docker rm 容器ID
docker rmi 镜像ID

或者强制删:

docker rmi -f 镜像ID

常见坑

坑1:删镜像报错

Error response from daemon: conflict: unable to delete image (must be forced) - image is being used by stopped container

原因: 有停止的容器在用这个镜像。

解决: 先删容器,或者强制删。

坑2:删了镜像,数据还在

镜像删了,但卷还在,数据没丢。

原因: 数据存在卷里,和镜像分开的。

这是好事! 重新起容器挂载同一个卷,数据就回来了。

坑3:docker system prune删多了

把还要用的镜像也删了。

解决: 重要镜像别删,重新pull就行。

坑4:清理完磁盘还是满的

Docker清理了,但磁盘还是100%。

原因: Docker日志文件太大了。

解决: 清理容器日志:

truncate -s 0 /var/lib/docker/containers/*/*-json.log

或者配置日志大小限制。

坑5:构建缓存占空间

docker builder prune

清理构建缓存。

十、定期清理

可以加个定时任务,每周清理一次:

crontab -e

加:

0 3 * * 0 /usr/bin/docker system prune -a -f --filter "until=168h"

每周日凌晨3点清理一周前的。

总结

常用清理命令:

命令 说明
docker system df 看占用空间
docker container prune 清理停止的容器
docker image prune 清理悬空镜像
docker volume prune 清理无用卷
docker system prune -a 一键全清

记住: 定期清理,别等磁盘满了再弄。

遇到问题加QQ23979811 协助处理


emer 发布于  2026-10-8 08:10 

Linux日志过大占用磁盘,logrotate日志切割配置

前言

服务器跑了几个月,突然磁盘满了,一查发现是日志文件占了几十G。Nginx的access.log、MySQL的慢查询日志、系统日志……这些日志文件只会越来越大,不会自己变小。手动删了吧,又怕删出问题;不删吧,磁盘迟早满。Linux 自带了 logrotate 工具,专门用来自动切割和清理日志,配置一次以后就不用管了。本文就详细讲一下怎么用 logrotate 管理日志。

什么是 logrotate

logrotate 是 Linux 系统自带的日志管理工具,可以自动完成:

  • 切割日志:把大日志文件按天/按大小切成多个小文件
  • 压缩日志:旧的日志自动 gzip 压缩
  • 删除日志:保留指定天数后自动删除
  • 通知服务:切割完后通知 Nginx/MySQL 等服务重新打开日志文件

系统默认每天运行一次 logrotate,你只需要写好配置文件就行。

logrotate 配置文件结构

全局配置

vi /etc/logrotate.conf

这是全局配置文件,一般不用改。里面定义了默认的行为:

weekly                  # 默认每周切割一次
rotate 4                # 保留4个日志文件
create                  # 切割后创建新的空日志文件
dateext                 # 用日期作为扩展名
include /etc/logrotate.d   # 包含这个目录下的所有配置

单个服务的配置

每个服务的日志配置放在 /etc/logrotate.d/ 目录下:

ls /etc/logrotate.d/

比如 nginx、mysql、syslog 都有各自的配置文件。

实战:配置 Nginx 日志切割

我们以 Nginx 为例,写一个完整的 logrotate 配置。

1. 创建配置文件

vi /etc/logrotate.d/nginx

2. 写入配置

/var/log/nginx/*.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 644 nginx nginx
    postrotate
        /usr/bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
    endpostrotate
}

3. 参数说明

参数 作用
/var/log/nginx/*.log 要切割的日志文件路径
daily 每天切割一次
rotate 30 保留30个日志文件
compress 旧日志用gzip压缩
delaycompress 延迟压缩,新切割的当天不压缩
missingok 日志文件不存在不报错
notifempty 空文件不切割
create 644 nginx nginx 创建新文件,权限644,属主nginx
postrotate...endpostrotate 切割后执行的命令,通知Nginx重新打开日志文件

常用切割策略

按天切割,保留30天

/var/log/nginx/*.log {
    daily
    rotate 30
    compress
    missingok
    notifempty
    create 644 nginx nginx
    postrotate
        /bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
    endpostrotate
}

按大小切割,超过100M就切

/var/log/nginx/access.log {
    size 100M
    rotate 10
    compress
    missingok
    notifempty
    create 644 nginx nginx
    postrotate
        /bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
    endpostrotate
}

同时按天+按大小

/var/log/nginx/*.log {
    daily
    size 100M
    rotate 30
    compress
    missingok
    notifempty
    create 644 nginx nginx
    postrotate
        /bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
    endpostrotate
}

意思是每天检查一次,如果日志超过100M就切割。

手动测试 logrotate

配置完之后,可以用 debug 模式测试一下,不会真正执行:

logrotate -d /etc/logrotate.d/nginx

参数说明:

  • -d:debug模式,只显示会做什么,不真正执行

如果没问题,手动执行一次:

logrotate -f /etc/logrotate.d/nginx
  • -f:强制切割,不管到没到时间

常见坑

坑1:切割了但服务还在写旧文件

很多人配置完 logrotate,发现日志切完了,但磁盘空间没释放。这是因为 Nginx 还在往旧的日志文件里写(虽然名字改了,但文件句柄还在)。

解决: 一定要配置 postrotate 脚本,通知服务重新打开日志文件。对于 Nginx,就是发送 USR1 信号:

postrotate
    /bin/kill -USR1 `cat /run/nginx.pid`
endpostrotate

坑2:压缩延迟没开,旧日志还占着空间

如果不加 delaycompress,切割完立刻就压缩,但服务可能还在写旧文件,导致压缩失败或者压缩不完整。

解决: 加上 delaycompress,让新切割的日志第二天再压缩。

坑3:日志文件权限不对

切割完创建的新日志文件,如果属主不对,Nginx 就写不进去。

解决: 用 create 644 nginx nginx 指定新文件的属主和权限。

坑4:logrotate 不执行

配置写完了,但日志从来没切割过。检查一下:

# 看logrotate的cron任务有没有
cat /etc/cron.daily/logrotate

# 手动执行一次看有没有报错
logrotate -d /etc/logrotate.d/nginx

总结

logrotate 配置的核心步骤:

  1. 在 /etc/logrotate.d/ 下创建配置文件
  2. 指定日志路径、切割频率、保留数量
  3. 加上 postrotate 通知服务重新打开日志
  4. 用 logrotate -d 测试配置
  5. 系统每天自动执行,不用管了

日志切割是服务器运维的基本功,配好了以后磁盘永远不会被日志撑满。

遇到问题加QQ23979811 协助处理


emer 发布于  2026-10-5 07:33 
'); })();