最近在服务器上遇到一个诡异的事情,磁盘空间每天都达到上限,好不容易腾出一些空间,好几 G 的存储马上被占完;加上 df -ha
和其他一些工具统计的存储大小相差太大,本来我也懒得去找原因。
但我实在腾不出多余的空间了:总共 100 G 的存储,所有工具都只显示只使用了 40G+,唯独 df
显示剩余空间 4KB…
起初我以为是那些工具没有统计到隐藏或者非权限文件,但我已经是 root 用户,再不济 sudo
命令也用了,依然只使用 40G+。
然后,我怀疑最近编译的项目太多,随便一个都至少需要 1G 空间…
但这些都不是根本原因 :)
原因在这:Ubuntu server: hard drive always full
df 根据文件系统的元数据来统计块大小(所以它出结果很快),而 du/dust/ncdu 之类的统计工具会基于目录树,也就是遍历目录(更慢)。
然而对于在进程中打开的文件,如果直接从文件系统删掉它,那么该文件所占的空间并没有被释放,但会从目录中移除,这会造成 df 和 du 统计结果不一致。
lsof +L1
命令(需要管理员权限),显示所有挂载为延迟卸载(Lazy Unmount)的文件系统。挂载为延迟卸载的文件系统意味着,即使文件系统不再被任何进程使用,它也不会立即被卸载。 这通常用于系统维护或当文件系统需要被安全地卸载时。
我运行它的结果如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NLINK NODE NAME
CmsGoAgen 394 root 2u REG 252,1 0 0 393345 /usr/local/cloudmonitor/logs/panic.daemon.log (deleted)
CmsGoAgen 394 root 3u REG 252,1 0 0 393345 /usr/local/cloudmonitor/logs/panic.daemon.log (deleted)
rsyslogd 418 syslog 7w REG 252,1 49879654878 0 665386 /var/log/syslog (deleted)
rsyslogd 418 syslog 8w REG 252,1 2977351 0 771662 /var/log/auth.log (deleted)
rsyslogd 418 syslog 9w REG 252,1 347269 0 669068 /var/log/kern.log (deleted)
ntpd 479 ntp 4w REG 252,1 17901 0 655822 /var/log/ntp.log (deleted)
unattende 525 root 3w REG 252,1 339 0 657564 /var/log/unattended-upgrades/unattended-upgrades-shutdown.log.1 (deleted)
apache2 537 root 2w REG 252,1 805884 0 771623 /var/log/apache2/error.log (deleted)
apache2 537 root 7w REG 252,1 0 0 656011 /var/log/apache2/other_vhosts_access.log (deleted)
apache2 537 root 8w REG 252,1 8023582 0 771622 /var/log/apache2/access.log (deleted)
fupan-ser 591608 root 6u CHR 136,1 0t0 0 4 /dev/pts/1 (deleted)
apache2 1272515 www-data 2w REG 252,1 805884 0 771623 /var/log/apache2/error.log (deleted)
apache2 1272515 www-data 7w REG 252,1 0 0 656011 /var/log/apache2/other_vhosts_access.log (deleted)
apache2 1272515 www-data 8w REG 252,1 8023582 0 771622 /var/log/apache2/access.log (deleted)
apache2 1272516 www-data 2w REG 252,1 805884 0 771623 /var/log/apache2/error.log (deleted)
apache2 1272516 www-data 7w REG 252,1 0 0 656011 /var/log/apache2/other_vhosts_access.log (deleted)
apache2 1272516 www-data 8w REG 252,1 8023582 0 771622 /var/log/apache2/access.log (deleted)
aliyun-se 1805451 root 7uW REG 252,1 0 0 917509 /tmp/AliyunAssistClientSingleLock.lock (deleted)
tmux:\x20 2674789 root 6u CHR 136,11 0t0 0 14 /dev/pts/11 (deleted)
我几个月前看到磁盘空间不太够,通过 dust 看到 /var/log
目录下日志文件几十 G,直接 rm -r
删了,但写入日志的系统进程始终在运行,系统日志文件没关闭, 从而磁盘空间没释放,所以这些文件都显示 deleted。其中的罪魁祸首是 rsyslogd 记录的系统日志,它占了 40G 空间,没被 du 统计到。
rsyslogd 是一个系统守护进程,用于在基于 Unix 和类 Unix 系统的计算机上记录消息。它是 rsyslog 软件套件的一部分,是 syslog 协议的一个实现,用于消息的传输和接收。rsyslogd 负责收集和处理来自系统上各种应用程序和服务的日志消息,并将它们写入到日志文件中。
显然,它会让系统日志文件一直打开,直接从磁盘上清理它,并不能释放它的空间。需要一些安全的做法:
sudo systemctl stop rsyslog
关闭服务进程,解除进程对文件的占用,然后清理文件,最后sudo systemctl start rsyslog
恢复服务- 或者使用
logrotate
日志管理工具,自动清除太久前的日志
呼~ 这些都是事后才知道的事情,那么回到只剩 4KB 的那种情况,我当时想通过重启系统,让这些进程在系统关机前自己结束,释放磁盘空间。
不过,在你决定重启之前,告知我已经这么做,但会出现问题的一个经验之谈:clickhouse、apache2 之类的服务,在重启时,会确保 /var/log
日志目录已经存在才能拉起,它们不会自动创建日志目录。由于我直接删除了它们的目录,当我通过 root 权限手动重新建立那些目录时,可能造成文件权限不够, 因为服务写入日志很可能不使用管理员权限。
那怎么办?我需要一个个查这些服务创建的账户是什么,然后切换到那些账户去建立吗?或者通过用户组,在同一级别的权限账户建立目录? 幸好我最近在更新系统,apt upgrade
会更新那些软件,到时候程序自己会重建这些日志目录,最终服务终于正常工作。
如果你不想遇到这个麻烦,那么最好不要关机来保持现有的服务运行,使用 lsof +L1
查看进程,想办法正常关闭那些进程来释放磁盘!