一、文件删除原理:
Linux通过link数量控制文件删除的,只有当一个文件i_count和i_link都为0,文件才被删除。
- i_count为当前文件被调用的数量(内存引用计数器,被进程调用时增加);
- i_link为介质连接数量(磁盘引用计数器,创建硬链接时增加)。
- rm删除文件改变的是i_link数。
二、查询方法
1、i_link命令:
- 查看i_link方法:
ls -ihl
- 举例:
[root@localhost shell_22_num]# ls -ihl
total 24K
103188844 drwxr-xr-x. 2 root root 6 Feb 1 23:26 directory
103188836 -rw-r--r--. 1 root root 2.4K Jan 31 22:37 num+.sh
103188841 -rw-r--r--. 1 root root 168 Jan 31 22:28 test1.sh
上图三个文件的i_count数量依次为2,1,1。
2、i_count命令:
- 查看文件被进程调用数情况:
fuser -uv [绝对路径文件名]
查看i_count方法说白了就是确认有哪些进程调用该文件。所以通过查询文件被使用情况便可知晓。-u指在每个进程后显示所属的用户名,-v指详细模式。
- 举例
[root@localhost shell_22_num]# fuser -uv /opt/shell/sexboy.txt
USER PID ACCESS COMMAND
/opt/shell//sexboy.txt: root 6266 f.... (root)sh
如图,可以看出该文件目前被root用户使用的进程sh调用,PID为6266。
三、文件删除方法
1、删除这个文件所有相关的硬链接 ——删除文件所有的入口
rm -rf [文件名] //所有硬链接及源文件文件
2、这个文件的进程调用数也为0 ——没有进程调用该文件
方法1:
fuser -ukv [绝对路径文件名] //-k代表杀死访问指定文件的所有进程
该方法有一个问题,就是在运行shell脚本(长ping 1000个包)时,使用该命令,成功关闭sh进程却不能取消整个Ping进程。。。我怀疑是我仅仅杀死了运行该ping命令的shell脚本的进程sh,而ping无影响。所以关闭进程方法推荐使用kill命令:
ps -ef|grep ping
kill -9 [进程PID]
方法2:
lsof |grep [文件路径]
lsof命令用于查看你进程开打的文件,打开文件的进程,进程打开的端口(TCP、UDP)。找回/恢复删除的文件。是十分方便的系统监视工具,因为lsof命令需要访问核心内存和各种文件,所以需要root用户执行。
使用该命令后,可以查看到调用该文件的程序名、PID,再通过kill命令关闭即可。
满足:
1、硬链接数=0;
2、进程调用数=0。
四、企业案例:
某个文件没有被彻底删除,导致的磁盘空间满了(df -h查看磁盘内文件空间使用值之和远小于磁盘总空间值,但使用率接近100%)。
分析可能原因:
某文件硬链接数为0,但进程调用数不为0(有人一直在使用该文件),它也会越来越大。
解决思路:
查找机器自身的服务,然后重启Apache和Tomcat。(总结:重启对应的软件)
模拟磁盘占满实验:
- 模拟思路:
向/var/log/secure 追加对应行数(往一个文件追加1亿行大约增加800多M,根据自身磁盘大小填写追加行数) - 准备工作:
- 进入/var/log/secure,并通过seq命令写入多行进行扩容。
[root@localhost log]# seq 1200000000 >>secure;echo "okay"
- 目前该文件(12G)已撑满我的磁盘。
[root@localhost log]# ls -lh|grep secure
-rw-------. 1 root root 12G Feb 3 23:24 secure
[root@localhost log]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 18G 18G 20k 100% /
- 排查工作:
- 在我们不知情哪个文件占满我们的磁盘情况下, 开始排查:
[root@localhost log]# du -sh /*|grep G
du: cannot access ‘/proc/7284/task/7284/fd/3’: No such file or directory
du: cannot access ‘/proc/7284/task/7284/fdinfo/3’: No such file or directory
du: cannot access ‘/proc/7284/fd/3’: No such file or directory
du: cannot access ‘/proc/7284/fdinfo/3’: No such file or directory
du: cannot access ‘/run/user/1001/gvfs’: Permission denied
4.9G /usr
13G /var
由此,可定位/var/文件夹占用空间大。继续深入排查:
[root@localhost log]# du -sh /var/*|grep G
12G /var/log
[root@localhost log]# du -sh /var/log/*|grep G
12G /var/log/secure
- 定文件后,进行判断大容量原因,是否可以删除。在此,我做删除处理。
/rm -f /var/log/secure
- 删除文件后,再次查看磁盘空间是否恢复正常。
[root@localhost log]# df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 471M 0 471M 0% /dev
/dev/sda3 18G 18G 20K 100% /
/dev/sda1 297M 229M 69M 77% /boot
[root@localhost log]# ls -ilh|grep secure
877821 -rw-------. 1 root root 24K Nov 10 16:00 secure-20191110
250932 -rw-------. 1 root root 6.3K Nov 23 15:10 secure-20191123
250881 -rw-------. 1 root root 1.3K Jan 26 06:08 secure-20200126
1145128 -rw-------. 1 root root 133K Feb 2 20:22 secure-20200202
神奇的情况出现了,文件已被删除,但是磁盘空间仍然被占满了。
此时,再次查询容量上G的文件,发现/var/中的大文件没了(说明确实删除了该文件的硬链接)。
[root@localhost log]# du -sh /*|grep G
du: cannot access ‘/proc/18191/task/18191/fd/3’: No such file or directory
du: cannot access ‘/proc/18191/task/18191/fdinfo/3’: No such file or directory
du: cannot access ‘/proc/18191/fd/3’: No such file or directory
du: cannot access ‘/proc/18191/fdinfo/3’: No such file or directory
du: cannot access ‘/run/user/1001/gvfs’: Permission denied
4.9G /usr
由此,得出结论:系统中的/var/log/secure文件没有被彻底删除。
- 如何找出系统中链接数为0,但调用数不为0的文件?使用命令lsof。
lsof命令用于查看你进程开打的文件,打开文件的进程,进程打开的端口(TCP、UDP)。找回/恢复删除的文件。是十分方便的系统监视工具,因为lsof命令需要访问核心内存和各种文件,所以需要root用户执行。
[root@localhost log]# lsof|grep /var/log/secure
lsof: WARNING: can't stat() fuse.gvfsd-fuse file system /run/user/1001/gvfs
Output information may be incomplete.
rsyslogd 1089 root 7w REG 8,3 12624556032 139531 /var/log/secure (deleted)
in:imjour 1089 1094 root 7w REG 8,3 12624556032 139531 /var/log/secure (deleted)
rs:main 1089 1095 root 7w REG 8,3 12624556032 139531 /var/log/secure (deleted)
进程名称 PID 文件大小(字节) 文件名
这里我通过文件路径当关键词进行搜索,其实他们通用的特点是在文件后附加(deleted)标记。
**(deleted)标记:**代表这个文件的硬链接数量为0,进程调用数不为0。
- 重启对应的程序
systemctl restart rsyslog.service
或
systemctl restart rsyslog
备注: 在centOS的早期版本,可能使用不同的重启命令,需要大家根据自身系统版本做调整。
比如命令:/etc/init.d/rsyslog restart等。
- 重启后,再次查看:
[root@localhost log]# df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 471M 0 471M 0% /dev
/dev/sda3 18G 6.0G 12G 34% /
/dev/sda1 297M 229M 69M 77% /boot
[root@localhost log]# lsof |grep /var/log/secure
rsyslogd 4267 root 7w REG 8,3 970 139513 /var/log/secure
in:imjour 4267 4269 root 7w REG 8,3 970 139513 /var/log/secure
rs:main 4267 4271 root 7w REG 8,3 970 139513 /var/log/secure
所有/var/log/secure后面的(deleted)均已消失,空间恢复正常,问题解决。
引申:
一般情况下,大多数服务(包括脚本)在运行时,是不能删除当前正在写入的日志文件的。这点请大家要牢记。这里特别说明。
就酱。