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。
五、常见坑
- 切割后服务还往旧文件写:缺postrotate里的
kill -USR1,或pid路径写错,导致旧文件越来越大; - 直接rm删正在写的日志:空间没释放,要
> 文件清空或重启服务; - compress和delaycompress一起用仍报错:第一次切出的文件先不压,第二次才压,别误以为没生效;
- 日志目录属主不对:create指定的用户组要真实存在,否则新建文件失败;
- cron没跑:确认
crond服务开机自启,否则logrotate永远不触发。
总结
在 /etc/logrotate.d/ 为每个大日志写一份切割规则,配好daily/size、rotate份数和postrotate信号重开日志,logrotate -f 验证一次,磁盘就不会再被单个日志吃满。
遇到问题加QQ23979811 协助处理
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
总结
记住:
- 用
df -h看磁盘使用率 - 用
du -sh /*看哪个目录大 - 用
find / -size +100M找大文件 - 先看日志,再看Docker,再看临时文件
- 删文件前确认不用了
- 删了没释放就重启进程
最常用:
df -h
du -sh /*
find / -type f -size +100M 2>/dev/null
遇到问题加QQ23979811 协助处理
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 协助处理
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 配置的核心步骤:
- 在
/etc/logrotate.d/下创建配置文件 - 指定日志路径、切割频率、保留数量
- 加上
postrotate通知服务重新打开日志 - 用
logrotate -d测试配置 - 系统每天自动执行,不用管了
日志切割是服务器运维的基本功,配好了以后磁盘永远不会被日志撑满。
遇到问题加QQ23979811 协助处理