根本原因是根分区写满导致SSHD会话初始化失败;须通过串口/救援模式进入系统,用df -hT和df -i定位满载挂载点及inode耗尽问题,再用du -xh和lsof +L1精准清理。

磁盘写满导致无法登录,根本原因是 SSH 进程启动时需要写入 ~/.bash_history、/var/run/utmp、临时 socket 文件等,而这些操作全部失败。此时不能等登录成功再查,必须从外部或最小化环境切入。
先用串口/救援模式进系统,别硬连 SSH
SSH 卡住或直接拒绝连接时,说明根分区(/)大概率已满到连 sshd 的会话初始化都失败。这时候:
- 云平台(如 Azure/AWS/腾讯云)优先打开串行控制台(Serial Console),它不依赖文件系统写入,能直接看到内核日志和 login 提示符
- 物理机或本地虚拟机可重启进
grub,编辑启动项,在 kernel 行末尾加systemd.unit=emergency.target或rd.break(RHEL/CentOS)进入紧急 shell - 若已配置
init=/bin/bash且 root 分区未加密,也可用此方式跳过 init 系统,但需手动 remount 为读写:mount -o remount,rw /
df -h 和 df -i 必须一起看,缺一不可
很多“无法登录”实际是 df -i 显示 IUse% 100%,而非空间耗尽。例如 /var/log/journal 下堆积数百万个 16KB 的 journal 文件,占满 inode 后,哪怕 df -h 还剩 2GB,也照样报 No space left on device。
- 执行
df -hT看哪个挂载点Use%接近 100%,重点关注/、/var、/tmp - 立刻跟
df -i,比对IUse%是否也爆掉;若只有IUse%高,就别删大文件,要去找小文件密集目录 - 特别注意
/var/spool/mail、/var/lib/docker/overlay2、/tmp/systemd-private-*这些地方,它们是 inode 杀手
du -x --max-depth=1 / | sort -hr 快速定位罪魁目录
du 默认会跨挂载点统计,比如 /data 是单独挂载的盘,但它在 / 下,du /* 就会把它也算进根分区占用,误导判断。加 -x 参数强制只统计当前文件系统。
- 先跑
du -xh --max-depth=1 / 2>/dev/null | sort -hr | head -10,看前 10 名谁最大 - 如果
/var异常高,立刻进/var:du -xh --max-depth=1 /var 2>/dev/null | sort -hr | head -10 - 常见真凶路径:
/var/log/journal(journald 日志)、/var/log/syslog(rsyslog)、/var/lib/rancher/k3s/agent/containerd(K3s 容器日志)、/var/cache/apt/archives(Debian 系未清理的 deb 包)
lsof +L1 查已删未释放的大文件,这是最隐蔽的元凶
运维删了 /var/log/nginx/access.log,但 nginx 进程还在往同一个 inode 写,文件没真释放——df 仍显示满,du 却找不到这个文件。这种“幽灵占用”必须靠 lsof 揭穿。
- 执行
lsof +L1(+L1 表示 link count = 0,即已被删除但句柄仍被持有) - 典型输出:
nginx 1234 root 1w REG 8,1 124567890 123456 /var/log/nginx/access.log (deleted) - 解决方法只有两个:
kill -USR1让服务重新打开日志(如kill -USR1 $(cat /var/run/nginx.pid)),或直接systemctl restart nginx - 注意:
lsof本身可能因磁盘满而启动失败,这时可尝试ls -l /proc/*/fd/ | grep deleted手动翻找
真正棘手的不是怎么删,而是删完后空间没释放——要么是进程还占着 deleted 文件,要么是误删了其他挂载点下的目录(比如 /data 其实是独立磁盘,但你清了 /data/logs 却以为在救根分区)。动手前务必确认路径归属,findmnt /path 比猜靠谱得多。











