1.问题描叙
根目录告警,使用率达到95%
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 45G 41G 2.3G 95% /
/dev/sda1 2.0G 52M 1.8G 3% /boot
tmpfs 5.9G 0 5.9G 0% /dev/shm
/dev/sdb 114G 79G 29G 74% /u01
发现oracle adump目录产生23G的audit log文件
[oracle@pcidecdb pcidec]$ du -sh $ORACLE_BASE/admin/pcidec/*
23G ./adump
3.3M ./bdump
4.0K ./cdump
4.0K ./dpdump
4.0K ./pfile
4.0K ./udump
大约500万+的文件
```bash
[oracle@pcidecdb adump]$ ls -alh|wc -l
5756918
当使用类似如下指令尝试删除大量文件时,遇到错误:/usr/bin/find: Argument list too long
```bash
find ./ +mtime 2 -type f|xargs -i rm -rf {}
或者
find . -type f -exec rm -rf {} \;
2.根因
上述命令中rm -rf {},{}会接受前面命令找到的文件列表,例如rm -rf {}会被替换为“rm -rf file1 file2 file3 file4”等。linux将分配了一个相对较小的内存缓冲区来存储这个参数列表,如果它被填满,shell 将不会执行该程序,并抛出Argument list too long异常
这个缓存区由ARG_MAX控制。在内核2.6.23上,限制设置为128 kB。在后续的版本有所增加,可以通过执行以下命令获取其值:
[oracle@pcidecdb adump]$ getconf ARG_MAX
131072
3.解决方案
3.1 for循环
除了 RAM/内存空间之外没有任何限制,但是根据运行表现来看,这种方式很慢,但更易于维护,因为它可以适应更复杂的场景
试运行以确定它将删除您期望的内容:
for f in *.aud; do echo rm "$f"; done
确认无误后执行它:
for f in *.aud; do rm "$f"; done
3.2 find
使用find”命令内置的“-delete”标志,费时11分50秒,按照上面查询得知总共5756918,大约每秒删除8108个文件
[oracle@pcidecdb pcidec]$time find /oracle/app/admin/pcidec/adump -maxdepth 1 -mtime +2 -name '*.aud' -delete
real 11m50.777s
user 0m4.682s
sys 1m44.428s
但是直接find 跟随-delete还是比较危险,在做之前,可以将delete换成print,后者会打印出要删除的文件
[oracle@pcidecdb pcidec]$time find /oracle/app/admin/pcidec/adump -maxdepth 1 -mtime +2 -name '*.aud' -print
再次验证成果,已经释放出约20G空间
[oracle@pcidecdb pcidec]$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 45G 19G 25G 43% /
/dev/sda1 2.0G 52M 1.8G 3% /boot
tmpfs 5.9G 0 5.9G 0% /dev/shm
/dev/sdb 114G 79G 29G 74% /u01
文件也从500万+减少到1万+
[oracle@pcidecdb adump]$ ls -alh|wc -l
11062