背景
最近服务器经常遇到磁盘占用空间满的告警,因此跟进定位问题后,发现原来是airflow的有好几个任务每分钟都在产生日志文件,导致磁盘空间占用率暴涨,因此想了几个策略:
- airflow降低日志文件输出大小,将原来
info
级别日志跳高到warning
- 定时清理日志文件
问题
问题就出现在清理日志文件,打算先清除一遍,主要清除一个月以前的日志文件,命令为find /data/airflow/ -name '*.log' -and -mtime +30 -type f |xargs rm
。
但是等了半天发现日志文件一直无法清除掉,不知道为什么?
后面直接上机器删除文件,采用rm -rf ./*.log
,发现报错如下:
/bin/rm: argument list too long
原因: 删除文件中包含的小文件数量过多,通常是由于受到 shell 参数个数限制所致
虽然网上有其他方案可以快速解决,比如:find
减少文件数量。
这下子就搞的很郁闷了,后面上网找了方案,发现可以通过rsync
去快速删除大量文件,因此想记录总结一下。
原理
Linux文件存储原理
我们需要对Linux文件存储原理做一个基本的了解,Linux文件存储数据是放在一张inode 表
,里面每一个文件的节点,每个节点包括以下内容:
- 文件类型
- 权限
- UID,GID
i_nlink
链接数(指向这个文件名路径名称个数)i_count
使用数(指使用这个文件的进程数)- 该文件的大小和不同的时间戳
- 指向磁盘上文件的数据块指针
- 有关文件的其他数据
Linux文件真正删除的过程:
i_nlink=0
没有人进行链接使用,包括任何硬链接i_count=0
没有任何进程使用
rm原理
rm的原理:减少磁盘引用计数i_nlink
,就是减少其他文件对这个文件链接,实际并没有删除文件内容。
因此,如果日志文件正在其他进程使用,rm
并不是真正删除,i_count
并不会减少,因此也不会释放磁盘空间。
如果想要真正删除一个文件,还需要同时将i_count
降至0。
了解完rm的原理,也就真正明白为什么find /data/airflow/ -name '*.log' -and -mtime +30 -type f |xargs rm
命令会这么慢,因为它要去找日志文件的所有link链接,然后一一删除掉。
解决方案
最终在网上找了最佳解决方案,就是使用rsync
。
rsync
本身的就是将两个文件夹作同步使用,如何使用rsync
删除文件,步骤是这样子:
- 如果将一个空文件夹,同步到要删除的文件夹里,是不是等于将文件夹清空了呢?
很取巧的方式,但是也很有效果,具体命令如下:
#制造一个空文件夹 mkdir -p /opt/airflow/empty; #执行rsync同步空文件夹 rsync --delete-before -aO /opt/airflow/empty/ /opt/airflow/logs/;
命令详解:
--delete-before
接收者在传输之前进行删除操作-a
归档模式,表示以递归方式传输文件,并保持所有文件属性