查看原文
其他

Linux硬盘与文件系统(11)

Cloud研习社 Cloud研习社 2023-06-06

Linux的文件名是存放在父目录的block里面,并指向这个文件的inode节点,这个文件的inode节点再标记指向存放这个文件的block的数据块。我们删除一个文件,实际上并不是清除inode节点和block数据,只是在这个文件的父目录的block中,删除这个文件的名字,从而使这个文件名消失,并且无法指向这个文件的inode节点,当没有文件名指向这个inode节点的时候,会同时释放inode节点和存放个这个文件的数据块,并更新inode map和block map今后让这些位置可以用于放置其他文件数据。

Linux通过link的数量来控制文件删除的,只有当一个文件不存在任何link的时候,这个文件才追被删除,一般来说,每个文件都有2个link计数器:i_count和i_nlink。

i_count的意义是当期文件使用者的数量,i_nlink的意义是介质连接的数量(硬链接的数量)。

当一个文件被某一个进程引用时,对应i_count数量就会增加,当创建文件的硬链接的时候,对应i_nlink数就会增加。

对于删除命令rm而言,实际就是减少硬盘引用计数i_nlink。这里就会有一个问题,如果一个文件正在被某个进程调用,而用户却执行rm操作把文件删除了,那么会出现什么结果?

当用户执行rm操作删除文件后,再执行ls或其他文件管理命令,无法再找到这个文件了,但是引用这个删除文件的进程却在继续正常执行,依然能够从文件中正确的读取及写入内容,这又是为什么呢?

   这是因为rm操作只是把文件的i_nlink减少了,如果没有其他链接i_nlink就为0了,但由于该文件依然被进程引用,因此,此时文件对应的i_count并不为0,所以即使执行了rm操作,但系统依然没有删除这个文件,只有当i_nlink和i_count都为0的时候,这个文件才会真正删除,也就是说,还需要接触该进程的对该文件的调用才行。

   以上讲的:i_count和i_nlink是文件删除的真实条件,但是当文件没有被调用时,执行了rm操作删除文件后是否可以找回被删除的文件呢?

   前面说了,rm操作只是把文件的i_nlink减少了或者设置为0了,实际就是将文件名到inode的链接删除了,此时,并没有删除文件的实体。此时如果及时停止机器工作,数据是可以找回的;如果此时继续写入数据,那么新来的数据就可能会被分配到被删除的数据block里存放,此时文件就会被真正的删除了。


文件删除案例


  1. 服务器硬盘满故障深入解析

问题:硬盘显示被写满但是用du -sh /*查看时占用硬盘空间之和还远小于硬盘大小问的解决。即找不到硬盘分区是怎么被写满的。

# 查看硬盘分区大小
[root@www ~]# cat /etc/redhat-release
CentOS release 5.3 (Final)
[root@www ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 117G 111G  0   100%  /
/dev/sda1 145M 12M  126M  9%  /boot
tmpfs   3.0G 0   3.0G  0%  /dev/shm

这是一台web服务器(apache+tomcat+mysql)
通过dh -h命令查看 总大小117G,使用了111G
[root@www /]# fdisk -l
Disk /dev/sda: 146.8 GB, 146815733760 bytes
255 heads, 63 sectors/track, 17849 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
   Device Boot Start  End Blocks    Id  System
/dev/sda1   *    1  19 152586   83  Linux
/dev/sda2        20  2108 16779892+  82   Linux swap / Solaris
/dev/sda3      2109 17849 126439582+ 83  Linux
[root@www /]# fdisk -l /dev/sda3
Disk /dev/sda3: 129.4 GB, 129474132480 bytes
255 heads, 63 sectors/track, 15741 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk /dev/sda3 doesn't contain a valid partition table
==========================================================================================
# 使用du命令查看到底哪些目录占用了空间
[root@www /]# du -sh /*
8.6M /bin
6.1M /boot
2.8G /data ===》这里是DB目录
124K /dev
60M /etc
1.6G /home ===》这里是日志目录
120M /lib
24M /lib64
16K /lost+found
8.0K /media
0 /misc
12K /mnt
0 /net
8.0K /opt
0 /proc
614M /root
35M /sbin
8.0K /selinux
24K /server
8.0K /srv
0 /sys
24K /tmp
2.5G /usr
29G /var ==》这里是www目录
可以看出,上面所有目录之和 远小于总的空间占用111G,是什么占用了硬盘,还查不到呢?
---------------
解答:
出现上面问题原因:
在apache/tomcat服务在运行状态下,清空了运行服务的日志,这里是清理了当天或正在写入的apache及tomcat的日志文件,从而导致了上面问题。(有关原理细节见下文)
引申下:
一般情况下,大多数服务(包括脚本)在运行时,是不能删除当前正在写入的日志文件的。这点请大家要记牢。
本文的解决办法:
查找机器自身的服务,然后重起apache和tomcat。
重起apache后:
[root@www 07]# df -h
Filesystem  Size Used  Avail  Use%  Mounted on
/dev/sda3  117G 109G  2.3G  98%   /
/dev/sda1  145M 12M   126M  9%   /boot
tmpfs    3.0G  0   3.0G   0%   /dev/shm
重起tomcat后: 
[root@www ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 117G  38G 74G  34%   /
/dev/sda1 145M  12M 126M  9%   /boot
tmpfs   3.0G  0  3.0G  0%   /dev/shm
我们发现,重启以后,就有剩余空间了。
模拟环境:
安装httpd并配置log位置:
[root@preparelessons ~]# yum -y install httpd
[root@preparelessons ~]# systemctl start httpd
[root@preparelessons ~]# netstat -anp | grep 80
tcp 0      0 10.0.0.136:57902        39.155.141.16:80        TIME_WAIT -
tcp 0      0 10.0.0.136:40876        119.188.121.239:80      TIME_WAIT -
tcp6 0      0 :::80                   :::*                    LISTEN 7877/httpd
unix 3      [ ] STREAM CONNECTED 21806    1/systemd /run/systemd/journal/stdout
unix 3      [ ] STREAM CONNECTED 21805    3007/systemd-udevd

[root@preparelessons ~]# vim /etc/httpd/conf/httpd.conf
……

    #
    # If you prefer a logfile with access, agent, and referer information
    # (Combined Logfile Format) you can use the following directive.
    #
    CustomLog "/mnt/logs/access_log" combined
</IfModule>
创建一个小的文件系统用于存放上述日志:

[root@preparelessons ~]# dd if=/dev/zero of=/dev/sdd bs=8K count=10
[root@preparelessons ~]# mkfs -t ext4 /dev/sdd
[root@preparelessons ~]# tune2fs -c -1 /dev/sdd
[root@preparelessons ~]# mount -o loop /dev/sdd /mnt/logs
[root@preparelessons ~]# echo "I am Jason" >/var/www/html/index.html

重启httpd服务以便日志可以正常写入:

[root@preparelessons ~]# systemctl restart httpd

写个循环脚本访问httpd,使得httpd日志充满/mnt/logs整个空间:

for n in `seq 100000`;do curl -s 127.0.0.1>/dev/null;done

查看空间使用情况:


[root@preparelessons ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 18G 1.5G 17G 9% /
devtmpfs 476M 80K 476M 1% /dev
tmpfs 487M 0  487M 0% /dev/shm
tmpfs 487M 7.7M 479M 2% /run
tmpfs 487M 0  487M 0% /sys/fs/cgroup
/dev/sda1 187M 104M 83M 56% /boot
tmpfs 98M 0   98M 0% /run/user/0
/dev/loop1 73K 68K 0 100% /mnt/logs

下面开始问题复现:
错误的删除方案:

rm -f /mnt/logs/access_log

[root@preparelessons ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 18G 1.5G 17G 9% /
devtmpfs 476M 80K 476M 1% /dev
tmpfs 487M 0  487M 0% /dev/shm
tmpfs 487M 7.7M 479M 2% /run
tmpfs 487M 0  487M 0% /sys/fs/cgroup
/dev/sda1 187M 104M 83M 56% /boot
tmpfs 98M 0   98M 0% /run/user/0
/dev/loop1 73K 68K 0 100% /mnt/logs

此时空间并未释放(/mnt/logs),你知道原因吗?
查看被删除但仍由进程占用的文件名:

[root@preparelessons ~]# lsof | grep del
sshd       6994         root  mem       REG                8,3     11168   33690931 /usr/lib64/security/pam_faildelay.so
httpd      7123         root    7w      REG                7,1     55250         12 /mnt/logs/access_log (deleted)
httpd      7124       apache    7w      REG                7,1     55250         12 /mnt/logs/access_log (deleted)
httpd      7125       apache    7w      REG                7,1     55250         12 /mnt/logs/access_log (deleted)
httpd      7126       apache    7w      REG                7,1     55250         12 /mnt/logs/access_log (deleted)
httpd      7127       apache    7w      REG                7,1     55250         12 /mnt/logs/access_log (deleted)
httpd      7128       apache    7w      REG                7,1     55250         12 /mnt/logs/access_log (deleted)
httpd      7858       apache    7w      REG                7,1     55250         12 /mnt/logs/access_log (deleted)

解决问题:
先停掉模拟访问测试脚本,重启http服务:

[root@preparelessons ~]# systemctl restart httpd

查看处理结果:

[root@preparelessons ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 18G 1.5G 17G 9% /
devtmpfs 476M 80K 476M 1% /dev
tmpfs 487M 0  487M 0% /dev/shm
tmpfs 487M 7.7M 479M 2% /run
tmpfs 487M 0  487M 0% /sys/fs/cgroup
/dev/sda1 187M 104M 83M 56% /boot
tmpfs 98M 0   98M 0% /run/user/0
/dev/loop1 73K 14K 54K 21% /mnt/logs

总结:
较好的处理方法是清空,而不是删除日志:

[root@preparelessons ~]# > /mnt/logs/access_log

2. 模拟block有剩余但是inode被占满的情况


# 接上个例子的环境
[root@preparelessons logs]# touch jason{1..10} # 创建多个文件,把当前文件系统的inode占满
touch: cannot touch ‘jason4’: No space left on device
touch: cannot touch ‘jason5’: No space left on device
touch: cannot touch ‘jason6’: No space left on device
touch: cannot touch ‘jason7’: No space left on device
touch: cannot touch ‘jason8’: No space left on device
touch: cannot touch ‘jason9’: No space left on device
touch: cannot touch ‘jason10’: No space left on device

[root@preparelessons logs]# df -h # 查看/mnt/logs的空间是否有剩余
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 18G 1.5G 17G 9% /
devtmpfs 476M 80K 476M 1% /dev
tmpfs 487M 0  487M 0% /dev/shm
tmpfs 487M 7.7M 479M 2% /run
tmpfs 487M 0  487M 0% /sys/fs/cgroup
/dev/sda1 187M 104M 83M 56% /boot
tmpfs 98M 0   98M 0% /run/user/0
/dev/loop1 73K 14K 54K 21% /mnt/logs # 可用容量还有很多
[root@preparelessons logs]# df -i # 查看inode信息
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda3 9388032 32921 9355111 1% /
devtmpfs 121774   396  121378    1% /dev
tmpfs 124486     1  124485    1% /dev/shm
tmpfs 124486   734  123752    1% /run
tmpfs 124486    16  124470    1% /sys/fs/cgroup
/dev/sda1 97280   326   96954    1% /boot
tmpfs 124486     1  124485    1% /run/user/0
/dev/loop1 16    16       0  100% /mnt/log # inode已经被占满了,无可用的inode

出现上面这种情况,我们就只能想办法把大量的小文件删掉或移除到其余可以备份的地方。

今天的内容较多,就不在推送《每天进步一点点之linux命令》系列文章了。


手应知:    尝鲜Rocky Linux
《Linux基础及进阶》:    022 - Linux硬盘与文件系统(7)    023 - Linux硬盘与文件系统(8)    024 - Linux硬盘与文件系统(9)    025 - Linux硬盘与文件系统(10)    026 - Linux硬盘与文件系统(11)


看完本文有收获?请分享给更多人


推荐关注「Cloud研习社」,带你从零开始掌握云计算技术!

微信号|bjdream-1


Cloud研习社 · 

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存