一、为什么CentOS服务器磁盘空间会耗尽?
CentOS服务器磁盘空间耗尽是运维人员最常遇到的问题之一。当磁盘空间达到100%时,会导致系统无法写入新数据、数据库服务崩溃、Web服务器返回500错误、系统日志无法记录等严重问题。
磁盘空间耗尽的常见原因:
- 日志文件无限增长:/var/log/下的日志文件未配置轮转,持续累积
- 包管理器缓存:yum/dnf缓存占用大量空间(可达数GB)
- 旧内核未清理:每次更新内核都会在新的内核文件,旧版本未删除
- 应用程序数据:数据库、上传文件等持续增长
- 临时文件未清理:/tmp目录下的临时文件长期堆积
- inode耗尽:大量小文件导致inode用尽(即使磁盘空间有剩余)
二、监控磁盘空间使用
2.1 基础监控命令
# 查看所有挂载点的磁盘使用情况(人类可读格式)
df -h
# 查看指定目录的磁盘使用情况
df -h /home
# 查看当前目录各子目录的磁盘使用情况
du -h --max-depth=1 /var
# 找出大于100MB的文件
find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null | awk '{print $5, $9}'
# 实时查看磁盘I/O状态
iotop
# 查看inode使用情况
df -i
2.2 自动化监控脚本
创建 /usr/local/bin/disk-alert.sh:
#!/bin/bash
# 磁盘空间告警脚本
# 阈值:使用率超过80%时发送告警
THRESHOLD=80
EMAIL="admin@example.com"
HOSTNAME=$(hostname)
df -h | awk -v threshold="$THRESHOLD" '0+$5 >= threshold {print "告警:分区 " $6 " 使用率 " $5}' | \
while read LINE; do
echo "$HOSTNAME: $LINE" | mail -s "CentOS服务器磁盘空间告警" $EMAIL
done
配置定时任务(每小时检查一次):
# /etc/crontab
0 * * * * root /usr/local/bin/disk-alert.sh
2.3 使用Prometheus + Grafana监控
# prometheus.yml
scrape_configs:
- job_name: node
static_configs:
- targets: ['localhost:9100']
安装node_exporter:
wget https://github.com/prometheus/node_exporter/releases/download/v1.6.0/node_exporter-1.6.0.linux-amd64.tar.gz
tar xvf node_exporter-*.tar.gz
cd node_exporter-*
./node_exporter &
Grafana仪表盘模板ID:1860(Node Exporter Full)
三、清理日志文件
3.1 配置日志轮转(logrotate)
CentOS默认使用logrotate管理日志文件。
检查现有配置:
cat /etc/logrotate.conf
ls -la /etc/logrotate.d/
为自定义应用配置logrotate(创建 /etc/logrotate.d/myapp):
/var/log/myapp/*.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
create 0644 app app
sharedscripts
postrotate
systemctl reload myapp > /dev/null 2>&1
endscript
}
手动测试配置:
logrotate -d /etc/logrotate.d/myapp # 调试模式
logrotate -f /etc/logrotate.d/myapp # 强制执行
3.2 清理旧日志
# 清理30天前的日志文件
find /var/log -name "*.log" -mtime +30 -delete
# 清理所有.tar.gz压缩包
find /var/log -name "*.tar.gz" -delete
# 清空大型日志文件(不删除文件,避免服务中断)
truncate -s 0 /var/log/messages
truncate -s 0 /var/log/secure
3.3 配置systemd journal清理
CentOS 7+使用systemd journal记录日志。
配置journal清理(编辑 /etc/systemd/journald.conf):
[Journal]
Storage=persistent
Compress=yes
Seal=yes
SizeMax=500M
MaxFileSec=1day
MaxRetentionSec=7day
重启journald服务:
systemctl restart systemd-journald
手动清理旧journal日志:
# 查看当前journal大小
journalctl --disk-usage
# 清理7天前的日志
journalctl --vacuum-time=7d
# 限制journal最大为500MB
journalctl --vacuum-size=500M
四、清理包管理器缓存
4.1 清理yum缓存(CentOS 7)
# 清理所有yum缓存
yum clean all
# 仅清理过期缓存
yum clean expire-cache
# 清理rpm数据库缓存
rpm --rebuilddb
自动化清理(添加到 /etc/cron.weekly/cleanup):
#!/bin/bash
# 每周清理yum缓存
yum clean all
rm -rf /var/cache/yum/*
4.2 清理dnf缓存(CentOS 8+)
dnf clean all
五、清理旧内核
CentOS更新内核后会保留旧版本,占用/boot分区空间。
查看已安装的内核:
rpm -qa | grep kernel
保留当前使用的内核,删除旧内核:
# 查看当前使用的内核
uname -r
# 删除特定版本的内核(请谨慎操作!)
yum remove kernel-3.10.0-1160.el7.x86_64
# 自动保留最新2个内核,删除更旧的
package-cleanup --oldkernels --count=2
配置yum保留内核数量(编辑 /etc/yum.conf):
installonly_limit=2 # 最多保留2个内核
六、清理临时文件和缓存
6.1 清理/tmp目录
# 清理10天前的临时文件
find /tmp -type f -mtime +10 -delete
# 更安全的清理方式(仅清理特定用户的文件)
find /tmp -user nginx -type f -mtime +7 -delete
配置tmpwatch(CentOS 7):
# /etc/cron.daily/tmpwatch
/usr/sbin/tmpwatch 240 /tmp # 清理240小时(10天)前的文件
6.2 清理内存缓存
# 清理页缓存
sync; echo 1 > /proc/sys/vm/drop_caches
# 清理目录项和inode缓存
sync; echo 2 > /proc/sys/vm/drop_caches
# 清理所有缓存(谨慎使用)
sync; echo 3 > /proc/sys/vm/drop_caches
注意:清理内存缓存不会影响系统稳定性,但可能导致短期内性能下降(需要重新缓存)。
七、配置磁盘配额(Quota)
对于多用户服务器,配置磁盘配额可以防止单个用户占用过多空间。
7.1 启用Quota
# 1. 修改/etc/fstab,在需要启用quota的分区添加usrquota,grpquota
/dev/sda1 /home ext4 defaults,usrquota,grpquota 1 2
# 2. 重新挂载分区
mount -o remount /home
# 3. 创建quota数据库文件
quotacheck -cug /home
# 4. 启用quota
quotaon /home
7.2 设置用户配额
# 设置用户john的磁盘配额
edquota -u john
# 在编辑器中设置:
# soft limit:软限制(超过后警告)
# hard limit:硬限制(无法超过)
Disk quotas for user john (uid 500):
Filesystem blocks soft hard inodes soft hard
/dev/sda1 102400 512000 1024000 0 0 0
# 将配额设置复制到其他用户
edquota -p john user2 user3 user4
7.3 查看配额使用情况
# 查看用户配额
quota -u john
# 查看所有用户配额
repquota -a
八、使用LVM动态调整磁盘空间
LVM(Logical Volume Manager)允许动态调整磁盘空间,避免分区固定大小的限制。
8.1 扩展逻辑卷
# 1. 查看卷组剩余空间
vgs
# 2. 扩展逻辑卷(增加10GB)
lvextend -L +10G /dev/vg_data/lv_data
# 3. 扩展文件系统
# ext4文件系统:
resize2fs /dev/vg_data/lv_data
# xfs文件系统:
xfs_growfs /data
8.2 添加新磁盘到LVM
# 1. 创建物理卷
pvcreate /dev/sdb
# 2. 扩展卷组
vgextend vg_data /dev/sdb
# 3. 扩展逻辑卷(参考8.1)
lvextend -L +50G /dev/vg_data/lv_data
九、预防磁盘空间耗尽的最佳实践
9.1 分区规划
| 分区 | 大小 | 说明 |
|---|---|---|
| /boot | 1GB | 存放内核文件 |
| / | 20-50GB | 系统文件 |
| /var | 20-100GB | 日志、缓存 |
| /home | 剩余空间 | 用户数据 |
| swap | 1-2倍内存 | 交换空间 |
9.2 监控告警
配置以下告警规则:
1. 磁盘使用率 > 80%:警告
2. 磁盘使用率 > 90%:严重告警
3. inode使用率 > 80%:警告
4. 磁盘I/O等待 > 30%:性能告警
9.3 定期清理任务
# /etc/cron.weekly/disk-cleanup
#!/bin/bash
# 清理yum缓存
yum clean all
# 清理旧日志
find /var/log -name "*.log.*.gz" -mtime +30 -delete
# 清理临时文件
find /tmp -type f -mtime +7 -delete
# 清理旧内核
package-cleanup --oldkernels --count=2
# 清理Docker镜像(如果使用Docker)
docker system prune -a --volumes
9.4 应用程序优化
# MySQL清理旧二进制日志
mysql -e "PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);"
# Docker清理未使用的镜像和容器
docker system prune -a --volumes
# Kubernetes清理已完成的Job
kubectl delete job --field-selector status.successful=1
十、常见问题与解决方案
Q1:df -h显示磁盘已满,但du找不到大文件?
A:可能是文件已被删除但仍被进程占用。
# 找出被删除但仍占用的文件
lsof | grep deleted
# 清空这些文件(不要直接删除)
truncate -s 0 /proc/进程ID/fd/文件描述符
Q2:/boot分区空间不足怎么办?
A:清理旧内核(参考第五章),或者重新安装内核包:
# 重新安装当前内核
yum reinstall kernel
# 清理/boot下的旧initramfs镜像
rm -f /boot/initramfs-*.img.old
Q3:如何快速释放磁盘空间?
A:按以下顺序操作:
1. 清理yum缓存:yum clean all
2. 清理旧日志:find /var/log -name "*.log.*.gz" -delete
3. 清理Docker镜像:docker system prune -a
4. 清理旧内核:package-cleanup --oldkernels --count=2
5. 清理临时文件:find /tmp -type f -mtime +7 -delete
Q4:inode耗尽怎么办?
A:inode耗尽通常是由于大量小文件导致的。
# 找出inode使用最多的目录
for i in /*; do echo $i; find $i | wc -l; done
# 清理大量小文件(例如缓存文件)
find /var/cache -type f -delete
十一、总结
防止CentOS服务器磁盘空间耗尽需要监控、清理、预防三管齐下:
- 监控:使用df、du、Prometheus等工具实时监控磁盘使用和inode使用
- 清理:配置logrotate、清理yum缓存、删除旧内核、清理临时文件
- 预防:使用LVM动态调整、配置磁盘配额、应用程序优化、定期清理任务
关键原则:
– 日志必须配置轮转(logrotate)
– 定期清理包管理器缓存
– 保留最新2个内核即可
– 重要数据不要放在系统分区
– 使用LVM提高灵活性
– 配置自动化监控和告警
通过本文的指南,你可以有效防止CentOS服务器磁盘空间耗尽,确保系统稳定运行。
最后提醒:磁盘空间监控是预防问题的关键,建议配置自动化监控和告警,在磁盘使用率达到80%时就及时处理。