一、先找出哪些文件占用了空间

当系统提示磁盘空间不足时,第一步就是要找出到底哪些文件占用了大量空间。Linux系统提供了几个非常实用的命令来帮助我们快速定位问题。

最常用的就是du命令,它可以显示目录或文件的磁盘使用情况。我推荐使用这个组合命令:

# 查看当前目录下各文件/目录的大小,按大小排序
du -h --max-depth=1 | sort -h

这个命令会显示当前目录下所有一级子目录和文件的大小,并按人类可读的格式(-h)从小到大排序。这样你一眼就能看出哪个目录最占空间。

如果想查看整个系统的磁盘使用情况,可以加上-x参数避免跨文件系统统计:

# 查看根目录下各目录的大小,排除其他挂载点
sudo du -xh --max-depth=1 / | sort -h

另一个更直观的工具是ncdu,它提供了一个交互式界面:

# 安装ncdu(如果尚未安装)
sudo apt install ncdu  # Debian/Ubuntu
sudo yum install ncdu  # CentOS/RHEL

# 扫描指定目录
ncdu /path/to/directory

使用方向键可以导航,按Enter进入子目录,d键删除文件,q退出。这个工具特别适合在SSH会话中使用。

二、清理常见的占用大户

找到占用空间的大文件后,接下来就是清理它们。以下是几个常见的"空间杀手"及其清理方法。

1. 日志文件

系统和服务日志往往会不断增长。使用journalctl可以清理系统日志:

# 查看journal日志占用的空间
journalctl --disk-usage

# 清理早于特定时间的日志
sudo journalctl --vacuum-time=7d  # 保留最近7天
sudo journalctl --vacuum-size=500M  # 限制总大小为500MB

对于特定服务的日志,比如nginx:

# 查看nginx日志大小
du -sh /var/log/nginx/

# 清空日志文件(注意:不是删除)
sudo truncate -s 0 /var/log/nginx/access.log
sudo truncate -s 0 /var/log/nginx/error.log

更好的做法是配置日志轮转(Logrotate),后面会详细介绍。

2. 缓存文件

Linux系统的包管理器会留下大量缓存:

# 清理apt缓存(Debian/Ubuntu)
sudo apt clean

# 清理yum缓存(CentOS/RHEL)
sudo yum clean all

# 清理dnf缓存(Fedora)
sudo dnf clean all

其他缓存位置包括:

  • /var/cache/ - 各种应用程序的缓存
  • ~/.cache/ - 用户级别的缓存

3. 旧的内核版本

系统升级后会保留旧内核,占用/boot分区空间:

# 查看已安装的内核(Debian/Ubuntu)
dpkg --list | grep linux-image

# 删除旧内核(保留最新的2-3个)
sudo apt autoremove --purge

三、使用高级工具深度清理

对于更复杂的清理需求,我们可以使用一些高级工具和技巧。

1. 查找并删除大文件

使用find命令查找大于特定大小的文件:

# 查找大于100MB的文件
sudo find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null

# 查找并删除7天前大于50MB的日志文件
sudo find /var/log -type f -name "*.log" -size +50M -mtime +7 -exec rm -f {} \;

2. 处理重复文件

重复文件也是空间浪费的常见原因。可以使用fdupes工具:

# 安装fdupes
sudo apt install fdupes  # Debian/Ubuntu
sudo yum install fdupes  # CentOS/RHEL

# 查找指定目录下的重复文件
fdupes -r /path/to/directory

# 查找并立即删除重复文件(保留一个副本)
fdupes -rdN /path/to/directory

3. 配置日志轮转

合理配置logrotate可以防止日志文件无限增长。编辑配置文件:

sudo nano /etc/logrotate.conf

示例配置(针对nginx):

/var/log/nginx/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        /usr/sbin/nginx -s reload >/dev/null 2>&1 || true
    endscript
}

这个配置表示:

  • 每天轮转一次日志
  • 保留14个旧日志文件
  • 压缩旧日志(除了当前的一个)
  • 如果日志为空则不轮转
  • 轮转后重新加载nginx

四、预防措施和最佳实践

清理磁盘空间只是治标,更重要的是建立预防机制。

1. 监控磁盘使用情况

设置定期监控,可以使用df命令:

# 查看所有文件系统的磁盘使用情况
df -h

# 只查看特定文件系统
df -h /dev/sda1

可以设置一个简单的cron任务,当磁盘使用超过阈值时发送警报:

# 编辑crontab
crontab -e

# 添加以下行(每天检查一次)
0 9 * * * [ $(df -h / | awk 'NR==2{print $5}' | tr -d '%') -gt 90 ] && echo "Disk space warning!" | mail -s "Disk Alert" admin@example.com

2. 合理分区

安装系统时就应考虑合理的分区方案:

  • / 根分区:30-50GB
  • /home:根据用户数据量
  • /var:单独分区,特别是运行服务的系统
  • /tmp:单独分区,可以挂载为tmpfs

3. 使用LVM管理磁盘

LVM(逻辑卷管理)可以动态调整分区大小:

# 查看当前逻辑卷
sudo lvs

# 扩展逻辑卷(假设VG有剩余空间)
sudo lvextend -L +10G /dev/mapper/vg-root
sudo resize2fs /dev/mapper/vg-root

4. 自动化清理脚本

创建一个定期运行的清理脚本:

#!/bin/bash

# 清理apt缓存
apt clean

# 清理旧日志
find /var/log -type f -name "*.gz" -mtime +30 -delete
find /var/log -type f -name "*.log" -mtime +7 -exec truncate -s 0 {} \;

# 清理用户缓存
find /home -type f -name "*.tmp" -mtime +7 -delete

# 发送报告
echo "Disk cleanup completed on $(date)" >> /var/log/cleanup.log

然后设置cron每周运行一次。

五、特殊场景处理

1. Docker磁盘清理

Docker会占用大量空间,特别是长时间运行后:

# 查看磁盘使用情况
docker system df

# 清理所有未使用的对象
docker system prune -a

# 删除所有停止的容器
docker container prune

# 删除所有未被任何容器使用的卷
docker volume prune

2. 处理已删除但未释放空间的文件

有时文件被删除但空间未被释放,因为仍有进程在使用:

# 查找被删除但仍被进程占用的文件
lsof | grep deleted

# 然后可以重启相关进程或服务
sudo systemctl restart servicename

3. 处理小文件过多的情况

大量小文件也会占用inode,导致"磁盘空间不足"的错误:

# 查看inode使用情况
df -i

# 查找包含大量文件的目录
find / -xdev -type f | cut -d "/" -f 2 | sort | uniq -c | sort -n

六、总结与建议

保持Linux系统磁盘空间充足需要定期维护和良好的使用习惯。以下是我的建议:

  1. 建立监控机制,在磁盘使用率达到80%时就应开始清理
  2. 为不同类型的文件分配专用分区(如/var、/home等)
  3. 配置合理的日志轮转策略
  4. 定期清理包管理器缓存和临时文件
  5. 对于开发环境,特别注意Docker和版本控制工具产生的数据
  6. 考虑使用LVM以便灵活调整分区大小
  7. 对大容量存储,考虑使用专门的存储服务器或云存储

记住,预防胜于治疗。与其等到磁盘空间耗尽才手忙脚乱地清理,不如建立自动化的维护机制。