場景描述
某天,收到Prometheus報警,生產中某台機器出現磁盤空間不足報警,該台服務器是mysql其中一台從庫,遠程登錄到該服務后,排查磁盤空間的原因,發現mysql日志文件過多,於是清空日志文件,但是日志清理后,發現磁盤空間並沒有釋放,下面分析處理過程和原因
日志清理后,查看磁盤空間
[root@hhjy3-21 ~]# df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/sda3 xfs 98G 65G 33G 73% /
devtmpfs devtmpfs 1.5G 0 1.5G 0% /dev
tmpfs tmpfs 1.5G 0 1.5G 0% /dev/shm
tmpfs tmpfs 1.5G 8.9M 1.5G 1% /run
tmpfs tmpfs 1.5G 0 1.5G 0% /sys/fs/cgroup
/dev/sda1 xfs 1014M 120M 895M 12% /boot
tmpfs tmpfs 293M 0 293M 0% /run/user/0
原因
在Linux或Unix系統中,通過使用rm刪除文件的原理,rm命令只是從文件系統的目錄結構上解除鏈接(unlink),也就是說如果文件是被打開的(有一個進程正在使用該文件句柄),那該進程還是可以讀取已刪除的文件,而我刪除的正是在運行中的MySQL的Logs,刪除的時候文件正在被使用中,所以並不釋放磁盤空間。
解決方法
Linux中使用lsof | grep deleted
命令可以獲取一個已經被刪除但是仍然被應用程序占用的文件列表
[root@hskj3-21 ~]# lsof | grep -i delete
mysqld_sa 1311 root 2u CHR 136,0 0t0 3 /dev/pts/0 (deleted)
mysqld 1607 mysql 1w REG 8,3 312627 1700052 /mysql/3306/logs/mysql.log (deleted)
mysqld 1607 mysql 2w REG 8,3 312627 1700052 /mysql/3306/logs/mysql.log (deleted)
mysqld 1607 mysql 5u REG 8,3 0 134335687 /mysql/3306/tmp/ibz8LDOk (deleted)
mysqld 1607 mysql 6u REG 8,3 0 134374089 /mysql/3306/tmp/ibprHY8C (deleted)
mysqld 1607 mysql 7u REG 8,3 0 135173881 /mysql/3306/tmp/ibS7LjtV (deleted)
mysqld 1607 mysql 8u REG 8,3 0 134429856 /mysql/3306/tmp/ibX2QZcx (deleted)
mysqld 1607 mysql 12u REG 8,3 0 134429858 /mysql/3306/tmp/ibMxDsTQ (deleted)
mysqld 1607 mysql 21w REG 8,3 153673 1700035 /mysql/3306/logs/slow.log (deleted)
mysqld 1607 1609 mysql 1w REG 8,3 312627 1700052 /mysql/3306/logs/mysql.log (deleted)
......
用該命令后,我發現占用的文件列表非常多,我們需要將占用已刪除文件的進程
給一個一個的殺掉
[root@hskj3-21 ~]# kill -9 PID
在線清空文件
其實上面那種直接rm
刪除文件的方法非常危險,特別是針對MySQL,Mongodb,數據相關的服務,rm
刪除之后,沒法釋放空間,還得手動重啟
或者kill
這些數據相關的服務進程,會影響到業務。
可以使用以下方法,磁盤空間不足可以馬上釋放,也可以保證進程繼續向文件寫入日志,這種方法適合在線清理。
$ echo >xxx/log