硬盘空间消失之谜:Linux 服务器存储排查与优化全过程

news/2024/12/17 13:19:29/文章来源:https://www.cnblogs.com/deali/p/18612139

前言

最近线上服务经常出现一些奇奇怪怪的问题,比如网页上的静态资源加载不出来,或者请求后端莫名报错,又或者 Redis 报错…

当我 SSH 登录到服务器上时,更不对劲了,敲个命令都卡顿…

如果是以前没经验,或许会以为遇到了疑难杂症,但作为多年的 Linux 用户,我已经知道了这种种异常的背后是「存储空间已满」在作祟!

那么问题就来到了「硬盘空间去哪儿了?」

排查

先用 df 看个大概

首先是最常用的命令

df -h

先来看看各个磁盘和挂载点的情况

在我的服务器上执行这个命令之后发现,根目录的可用空间已经只剩下几百 KB 了…

再用 du 看具体

使用 du 命令可以查看各个子目录占用的空间,然后再结合 sort 命令排个序

sudo du -h --max-depth=1 / | sort -hr

参数说明:

  • 因为要直接统计根目录,所以需要有 root 权限
  • --max-depth=1:仅显示当前目录及其下一级子目录的占用情况。
  • sort -hr:按照大小进行降序排列。

查看目录的总占用空间:

du -sh /

更好的工具

前面的 du 命令,还是没那么好用,主要是列出来的数据太多了。

这次我用上了 ncdu 工具

ncdu 是一个更加用户友好的磁盘使用分析工具,支持交互式界面。

不过很多发行版没有内置,需要先安装:

sudo apt install ncdu

使用 ncdu 分析根目录占用

sudo ncdu -x /

使用 -x 参数可以限制扫描范围为当前文件系统,不跨越挂载点。因为根目录下有很多其他硬盘的挂载点,根据前面使用 df 命令的分析,是主硬盘满了,所以我只要看主硬盘的就行。

ncdu 启动之后会扫描各个文件的存储空间,然后进入一个交互式界面,可以很直观的看到各个目录的占用空间大小,从大到小排序。

罪魁祸首

在 ncdu 里可以很直观看到 /var/lib/docker 这个目录占用了 70% 以上的存储空间,妥妥的答辩啊!

使用 du 分析

sudo du -h --max-depth=1 /var/lib/docker | sort -hr

之后大概的占用情况是这样(只是例子,不是真实数据)

10G     /var/lib/docker/overlay2
5G      /var/lib/docker/volumes
1G      /var/lib/docker/containers
500M    /var/lib/docker/images

基本就是 docker 的镜像、容器日志、卷之类的把硬盘吃掉了

清理 Docker 的未使用资源

找到了问题,那就好办了

首先把没用的 docker 容器停掉

然后执行一下 docker 提供的一些清理命令。

清理未使用的资源(镜像、容器、卷和网络)

Docker 提供了 docker system prune 命令,能清理未使用的资源。

docker system prune -a
  • -a:删除所有未使用的镜像(包括没有关联到容器的镜像)。
  • 注意:这个命令不会删除被正在运行的容器依赖的资源,请小心操作。

仅清理未使用的卷

如果是 /var/lib/docker/volumes 占用空间较多:

docker volume prune

仅清理未使用的网络

如果是 /var/lib/docker/network 占用较多:

docker network prune

删除不需要的容器、镜像和卷

删除未运行的容器

docker container prune

删除无用的镜像

docker image prune -a

删除无用的卷

docker volume prune

清理旧的镜像和未使用的标签

如果在使用大量镜像,很多旧版本可能已经没有用了。

列出镜像按大小排序

docker images --format "{{.Repository}}:{{.Tag}} {{.Size}}" | sort -k2 -h

删除指定镜像

docker rmi <image-id>

啥玩意这么大?

在分析存储空间的占用过程中,我还发现有个文件特别离谱,下面这个文件,500多个G…

/var/lib/docker/containers/e4b5a99b429a612885417460214ea40a6a49a3360c29180af800ff7aef4c03df/e4b5a99b429a612885417460214ea40a6a49a3360c29180af800ff7aef4c03df-json.log

找出拉屎的容器

来看看是哪个容器拉的屎。

日志文件的路径中包含了容器的 ID:e4b5a99b429a612885417460214ea40a6a49a3360c29180af800ff7aef4c03df

来找一下是哪个容器:

docker ps | grep e4b5a99b429a

在容器列表中找不到该容器,可能它已经被停止或删除了。在这种情况下,可以使用 docker inspect 检查具体信息:

docker inspect e4b5a99b429a

分析日志内容

可以通过 tailless 查看日志内容,检查是否有异常输出:

sudo tail -n 50 /var/lib/docker/containers/e4b5a99b429a612885417460214ea40a6a49a3360c29180af800ff7aef4c03df/e4b5a99b429a612885417460214ea40a6a49a3360c29180af800ff7aef4c03df-json.log

日志的具体内容我就不贴了,看起来应该没啥问题,就是运行久了,日积月累…

处理这个问题的方法,见下一小节。

清理 docker 日志文件

如果 /var/lib/docker/containers 占用大量空间,可能是容器日志文件过大。

查看日志文件

每个容器的日志存储在 /var/lib/docker/containers/<container-id>/<container-id>-json.log

使用以下命令找到最大的日志文件:

sudo find /var/lib/docker/containers/ -type f -name "*.log" -exec du -h {} + | sort -hr | head -n 10

手动清理日志

清空一个特定容器的日志文件:

sudo truncate -s 0 /var/lib/docker/containers/<container-id>/<container-id>-json.log

设置日志文件大小限制

在 Docker 的配置文件中限制日志大小(推荐):

  1. 编辑 Docker 配置文件(通常是 /etc/docker/daemon.json):

    sudo nano /etc/docker/daemon.json
    
  2. 添加或修改以下配置:

    {"log-driver": "json-file","log-opts": {"max-size": "10m","max-file": "3"}
    }
    
    • max-size:单个日志文件最大 10 MB。
    • max-file:保留 3 个日志文件。
  3. 重新加载 Docker:

    sudo systemctl restart docker
    

迁移 /var/lib/docker 到新磁盘

可以将 /var/lib/docker 挂载到其他磁盘,从而缓解当前磁盘的存储压力。这是一个常见的做法,尤其在有多块磁盘的情况下。

方法一:直接迁移 /var/lib/docker 到新磁盘

停止 Docker 服务

在迁移数据之前,需要先停止 Docker 服务:

sudo systemctl stop docker

移动 /var/lib/docker 到新位置

假设新磁盘挂载在 /mnt/new-disk,执行以下命令:

sudo mv /var/lib/docker /mnt/new-disk/docker

创建软链接

将新的路径链接回 /var/lib/docker,让 Docker 继续按默认路径工作:

sudo ln -s /mnt/new-disk/docker /var/lib/docker

启动 Docker 服务

sudo systemctl start docker

验证

运行以下命令确保 Docker 正常工作:

docker info

方法二:修改 Docker 配置文件,指定新存储位置

停止 Docker 服务

sudo systemctl stop docker

移动 /var/lib/docker 到新磁盘

将现有数据迁移到新磁盘挂载点。例如,新磁盘挂载在 /mnt/new-disk

sudo mv /var/lib/docker /mnt/new-disk/docker

修改 Docker 配置

编辑 Docker 的配置文件(通常是 /etc/docker/daemon.json),指定新的存储路径:

sudo nano /etc/docker/daemon.json

添加或修改以下内容:

{"data-root": "/mnt/new-disk/docker"
}

启动 Docker 服务

sudo systemctl start docker

验证

再次检查 Docker 是否正常运行:

docker info | grep "Docker Root Dir"

你应该能看到新的路径(如 /mnt/new-disk/docker)。

方法三:直接挂载新磁盘到 /var/lib/docker

如果想直接将新磁盘作为 /var/lib/docker 的挂载点,可以使用以下方法

格式化新磁盘

假设新磁盘为 /dev/sdb1,先格式化并创建文件系统(如 ext4):

sudo mkfs.ext4 /dev/sdb1

挂载新磁盘

将新磁盘挂载到 /var/lib/docker

sudo mount /dev/sdb1 /var/lib/docker

迁移现有数据

如果 /var/lib/docker 目录下已有数据,需要先复制到新磁盘:

sudo rsync -a /var/lib/docker/ /mnt/new-disk/

然后再将新磁盘挂载回 /var/lib/docker

修改 /etc/fstab 确保开机自动挂载

编辑 /etc/fstab 文件,添加一行挂载配置:

/dev/sdb1  /var/lib/docker  ext4  defaults  0  2

注意事项

  1. 数据迁移风险:在迁移或重建 /var/lib/docker 时,务必备份重要数据(如持久卷数据)。

  2. 权限问题:确保新目录的权限与原始目录一致:

    sudo chown -R root:root /mnt/new-disk/docker
    
  3. 检查挂载点:确保新磁盘挂载成功,并设置自动挂载,避免系统重启后路径丢失。

通过以上方法,可以成功将 /var/lib/docker 挂载到其他磁盘,缓解存储压力并优化存储布局。

重建 /var/lib/docker

如果清理后空间仍然不足,可以重建 Docker 的存储目录(会删除所有容器、镜像和数据)

停止 Docker 服务:

sudo systemctl stop docker

备份现有 Docker 数据(可选):

sudo mv /var/lib/docker /var/lib/docker.bak

创建一个新的空目录:

sudo mkdir /var/lib/docker

启动 Docker 服务:

sudo systemctl start docker

总结

在这次 Linux 服务器硬盘空间消失问题的排查过程中,我经历了一次完整的存储分析和优化实战。

关键步骤概括:

  1. 初步排查存储占用情况
    • 使用 duncdu 等工具,快速定位占用空间较大的目录。
    • 发现 /var/lib/docker 目录占用了大量存储空间。
  2. 深入定位具体问题
    • 找到具体的容器日志文件路径,通过容器 ID 确认了是哪个容器产生了大量日志。
    • 使用 docker inspectdocker logs,进一步分析日志内容。
  3. 解决问题
    • 清空了过大的容器日志文件,通过 truncate 命令立即释放空间。
    • 修改 Docker 配置文件(daemon.json)限制了日志文件的大小,避免类似问题再次发生。
  4. 验证与优化
    • 重启 Docker 服务后,验证了服务正常运行。
    • 使用 docker system prune 清理了无用资源,并规划了日志管理策略。

个人收获与思考:

这次问题的解决让我深刻体会到以下几点:

  • 系统监控的重要性:及时监控存储使用情况,可以避免问题扩大化。
  • 日志管理最佳实践:过度增长的日志文件是常见的存储占用原因,必须设置合理的日志大小限制。
  • 工具的高效使用duncdu 和 Docker 命令等工具在排查问题中大大提升了效率。
  • 日常维护习惯:定期清理无用的容器资源(例如停止的容器、未使用的镜像),可以保持系统健康运行。

这次实践不仅解决了磁盘空间问题,也让我对 Linux 系统管理和 Docker 的运维有了更深的理解。在未来的运维工作中,我将更加注重系统的监控与优化,提前预防类似问题的发生。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/854287.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#调用Python代码的方式(二),以PaddleOCR-GUI为例

前言 前面介绍了在C#中使用Progress类调用Python脚本的方法,但是这种方法在需要频繁调用并且需要进行数据交互的场景效果并不好,因此今天分享的是C#调用Python代码的方式(二):使用pythonnet调用Python代码。 pythonnet介绍 Python.NET 是一个包,为 Python 程序员提供了与…

在线教育系统厂家电话

为了方便您直接对接相关业务,下面提供几个在线教育相关企业的联系电话,请自行选择合适的服务商联系。若想直接获取更多信息或定制化的产品方案,请拨打以下联系电话:- 顺企网在线教育直播软件开发平台联系人:张生;联系方式:电话 15989102540(说明您来自顺企网,可获得优…

如何解决Git合并冲突?

讲个故事先: 一个晴朗的日子,Alex 把远程版本库的修改拉到他的本地版本库。 他修改了名为 abc.txt 的文件,将其暂存(staged),提交(committed),最后推送(pushed)回远程版本库。 同时,Tina 不知道 Alex 对abc.txt文件的修改,在该文件的 相同区域 做了一些修改,并尝…

MongoDB备份脚本

#!/bin/bash #backup MongoDB #mongodump命令路径 DUMP=/home/mongodb/bin/mongodump #临时备份目录 OUT_DIR=/home/mongodb_bak/mongodb_bak_now #备份存放路径 TAR_DIR=/home/mongodb_bak/mongodb_bak_list #获取当前系统时间 DATE=`date +%Y_%m_%d` #数据库账号 DB_USER=roo…

SQL Server创建用户一直提示用户已存在的解决办法

背景:复制的老数据库,创建账号onlyread时,一直提示数据库里有这个用户名。报错如下:“用户、组或角色onlyread在当前数据库中已存在。”解决方法: 1. 查询数据库,是否有这个用户 -- 查询是否存在指定的用户、组或者角色 SELECT * FROM sys.database_principals WHERE na…

jquery目录树插件

file-explore是一款简单的jquery目录树插件。它使用嵌套的无序列表作为目录树的结构,结合font-awesome图标可以制作出非常漂亮的jquery目录树效果。在线预览 下载使用方法 在页面中引入file-explore.css和font-awesome文件,以及jquery和file-explore.js文件。<link rel=&…

SQL Server的数据库备份与还原

数据库备份分类 备份分类完全备份:(常用方式)备份整个数据库,包含用户表、系统表、索引、视图和存储过程等所有数据库对象。 因而,占用不少时间和空间,这种方式不建议太频繁,一般一周一次。差异备份:也叫增量备份。它不使用事务日志,相反,它使用整个数据库的一种新映…

vue-实现组件是否显示还是隐藏

比如我们在home页面需要这个标签在city页面不需要这个标签我们可以在router里面添加meta属性在需要的组件页面导入route实力获取meta属性的值

教育行业办公软件排行榜揭晓!J 人备考该选谁?

在教育领域,高效的办公软件对团队协作和个人学习意义重大。尤其对于 J 人,其偏好秩序与规划,可视化团队协作办公软件能助其在教育教培团队运作和个人公考备考中精准把控进程。本文将盘点 6 款此类软件,助力相关人士做出合适选择。 一、板栗看板 板栗看板是教育办公软件中的…

github克隆代码报错

报错一: git clone https://github.com/PanJiaChen/vue-admin-template.git报错 Cloning into vue-admin-template... fatal: unable to access https://github.com/PanJiaChen/vue-admin-template.git/: Failed to connect to github.com port 443 after 21219 ms: Timed out…

Vulnhub 靶场 DevGuru: 1

前期准备 靶机地址:https://www.vulnhub.com/entry/devguru-1,620/ kali攻击机IP:192.168.11.128 靶机IP:192.168.11.130 一、信息收集 1.使用nmap对目标靶机进行扫描开了 22、80、8585 端口。发现 git 目录,且提示做解析: 192.168.11.130 devguru.local 2. 80 端口发现用…

proxifier 抓取指定客户端软件数据包

背景 想要抓取指定Windows 客户端软件的数据包;过滤掉全局代理的无序数据包。 下载地址 https://www.proxifier.com/ 配置步骤 1. 配置 Proxy Servers2. 代理服务配置 3.Proxification Rules 配置需要监听的小程序,选择上一步配置的代理服务 任务管理器章选择想要抓包的进程…