• Linux下文件删除的原理


    linux下文件删除的原理:

    Linux 是通过 Link 的数量来控制文件删除的,只有当一个文件不存在任何 link 的时候,这个文件才会被删除。 

    一般来说,每个文件都有2个link计数器:

    • i_count
      • 进程的引用计数
    • i_link 
      • 硬链接数量

    i_count的意义是当前文件使用者(或被调用)的数量; 

    i_link 的意义是介质连接的数量。

     

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

     

    对于删除命令rm而言,实际就是减少磁盘引用计数i_link。
    这里就会有一个问题,如果一个文件正在被某个进程调用,而用户却执行rm操作把文件删除了,那么会出现什么结果呢?
    当用户执行rm操作删除文件后,再执行ls或者其他文件管理命令,无法再找到这个文件了,但是调用这个删除的文件的进程却在继续正常执行,依然能够从文件中正确的读取及写入内容。这又是为什么呢?

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

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

    前面说了,rm操作只是将文件的i_link减少了,或者说置0了,实际就是将文件名到inode的链接删除了,此时,并没有删除文件的实体即(block数据块),此时,如果及时停止机器工作,数据是可以找回的,如果此时继续写入数据,那么当新数据就可能会被分配到被删除的数据的block数据块,此时,文件就会被真正的回收了,那时就是神仙也没有办法了。


    文件删除生产场景案例解决实战 

    1. Web服务器磁盘满故障深入解析 https://blog.51cto.com/oldboy/612351
    2. 磁盘满的故障(inode满了)
     

    案例实战环境模拟:

    1. 安装 httpd web 服务

    # 安装 httpd
    yum install httpd -y
    
    # 开启服务
    [root@oldboy test]# /etc/init.d/httpd start
    Starting httpd: httpd: apr_sockaddr_info_get() failed for oldboy
    httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
                                                               [  OK  ]
    
    # 查看80端口,表示服务已经运行
    [root@oldboy test]# lsof -i :80
    COMMAND  PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
    httpd   4801   root    4u  IPv6  39743      0t0  TCP *:http (LISTEN)
    httpd   4803 apache    4u  IPv6  39743      0t0  TCP *:http (LISTEN)
    httpd   4804 apache    4u  IPv6  39743      0t0  TCP *:http (LISTEN)
    httpd   4805 apache    4u  IPv6  39743      0t0  TCP *:http (LISTEN)
    httpd   4806 apache    4u  IPv6  39743      0t0  TCP *:http (LISTEN)
    httpd   4807 apache    4u  IPv6  39743      0t0  TCP *:http (LISTEN)
    httpd   4808 apache    4u  IPv6  39743      0t0  TCP *:http (LISTEN)
    httpd   4809 apache    4u  IPv6  39743      0t0  TCP *:http (LISTEN)
    httpd   4810 apache    4u  IPv6  39743      0t0  TCP *:http (LISTEN)
    
    # 编辑配置文件,让日志记录到/app/log 下面
    cd /etc/hpptd/conf 
    vi /etc/httpd/conf # 查看CustomLog logs/access_log common 的参数在哪一行,退出来用sed命令替换。
    
    # 先grep过滤确认替换的文本值是否唯一
    [root@oldboy conf]# grep "CustomLog logs/access_log common" httpd.conf 
    #CustomLog logs/access_log common
    
    # 将日志路径从logs/access_log替换成/app/logs/access_log
    # 注意,因为要将‘#’除掉,所以sed命令替换的分隔符换成了 ‘@’
    [root@oldboy conf]# sed -i 's@#CustomLog logs/access_log common@CustomLog /app/logs/access_log common@g' httpd.conf 
    [root@oldboy conf]# grep "CustomLog logs/access_log common" httpd.conf 
    
    # 确认替换结果
    [root@oldboy conf]# grep "CustomLog /app/logs/access_log common" httpd.conf  
    CustomLog /app/logs/access_log common

    关闭防火墙:

    [root@oldboy test]# /etc/init.d/iptables stop
    iptables: Setting chains to policy ACCEPT: filter          [  OK  ]
    iptables: Flushing firewall rules:                         [  OK  ]
    iptables: Unloading modules:                               [  OK  ]

    2. 创建一个小的文件系统,用于存放上述日志

    # bs是块大小,count是块数量
    [root@oldboy conf]# dd if=/dev/zero of=/dev/sdc bs=8K count=10
    10+0 records in
    10+0 records out
    81920 bytes (82 kB) copied, 0.000283861 s, 289 MB/s
    
    
    [root@oldboy conf]# ls -l /dev/sdc
    -rw-r--r-- 1 root root 81920 Sep  5 23:58 /dev/sdc
    
    # 格式化创建文件系统
    [root@oldboy conf]# mkfs -t ext3 /dev/sdc          
    mke2fs 1.41.12 (17-May-2010)
    /dev/sdc is not a block special device.
    Proceed anyway? (y,n) y
    Filesystem label=
    OS type: Linux
    Block size=1024 (log=0)
    Fragment size=1024 (log=0)
    Stride=0 blocks, Stripe width=0 blocks
    16 inodes, 80 blocks
    4 blocks (5.00%) reserved for the super user
    First data block=1
    1 block group
    8192 blocks per group, 8192 fragments per group
    16 inodes per group
    
    Writing inode tables: done                            
    
    Filesystem too small for a journal
    Writing superblocks and filesystem accounting information: done
    
    This filesystem will be automatically checked every 22 mounts or
    180 days, whichever comes first.  Use tune2fs -c or -i to override.
    
    # 取消180天的检查(可做可不做)
    [root@oldboy conf]# tune2fs -c -1 /dev/sdc         
    tune2fs 1.41.12 (17-May-2010)
    Setting maximal mount count to -1
    
    
    # 设置挂载点和存放日志的目录
    [root@oldboy conf]# mkdir /app/logs -p
    [root@oldboy conf]# mount -o loop /dev/sdc /app/logs
    
    # 查看是否挂载成功
    [root@oldboy conf]# df -h
    Filesystem      Size  Used Avail Use% Mounted on
    /dev/sda3       6.9G  1.5G  5.1G  23% /
    tmpfs           499M     0  499M   0% /dev/shm
    /dev/sda1       190M   36M  145M  20% /boot
    /dev/sdc         73K   14K   55K  21% /app/logs

    成功模拟了一个73K的小磁盘。

     

    3. 重启httpd服务,确保日志记录到了上述文件系统挂载的/app/log下面

    [root@oldboy conf]# /etc/init.d/httpd restart
    Stopping httpd:                                            [  OK  ]
    Starting httpd: httpd: apr_sockaddr_info_get() failed for oldboy
    httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
                                                               [  OK  ]

    访问localhost或127.0.0.1或Linux的ip地址,可以访问网站,然后/app/logs/access_log中会生成日志文件。

     

    另起一个会话查看访问的动态:tail -f /app/logs/access_log 

     
    为了快速塞满日志文件,循环访问:
    [root@oldboy conf]# echo oldboy >/var/www/html/index.html
    
    [root@oldboy conf]# for n in `seq 100`
    > do 
    >     curl 127.0.0.1
    > done

    查看硬盘使用情况,发现日志盘已经满了:

    [root@oldboy conf]# df -h
    Filesystem      Size  Used Avail Use% Mounted on
    /dev/sda3       6.9G  1.5G  5.1G  23% /
    tmpfs           499M     0  499M   0% /dev/shm
    /dev/sda1       190M   36M  145M  20% /boot
    /dev/sdc         73K   73K     0 100% /app/logs

    删除日志文件,查看硬盘空间,发现硬盘还是满的。

    [root@oldboy conf]# rm /app/logs/access_log
    rm: remove regular file `/app/logs/access_log'? y
    [root@oldboy conf]# df -h
    Filesystem      Size  Used Avail Use% Mounted on
    /dev/sda3       6.9G  1.5G  5.1G  23% /
    tmpfs           499M     0  499M   0% /dev/shm
    /dev/sda1       190M   36M  145M  20% /boot
    /dev/sdc         73K   73K     0 100% /app/logs

    查看被删除的但仍由进程占用的文件名:

    [root@oldboy conf]# lsof |grep del
    rdisc     3212      root    0u      CHR              136,0      0t0          3 /dev/pts/0 (deleted)
    httpd     4957      root    7w      REG                7,0    59356         12 /app/logs/access_log (deleted)
    httpd     4959    apache    7w      REG                7,0    59356         12 /app/logs/access_log (deleted)
    httpd     4960    apache    7w      REG                7,0    59356         12 /app/logs/access_log (deleted)
    httpd     4961    apache    7w      REG                7,0    59356         12 /app/logs/access_log (deleted)
    httpd     4962    apache    7w      REG                7,0    59356         12 /app/logs/access_log (deleted)
    httpd     4963    apache    7w      REG                7,0    59356         12 /app/logs/access_log (deleted)
    httpd     4964    apache    7w      REG                7,0    59356         12 /app/logs/access_log (deleted)
    httpd     4965    apache    7w      REG                7,0    59356         12 /app/logs/access_log (deleted)
    httpd     4966    apache    7w      REG                7,0    59356         12 /app/logs/access_log (deleted)
    tail      8895      root    3r      REG                7,0    59356         12 /app/logs/access_log (deleted)
    [root@oldboy conf]# 

    4. 重启httpd 服务 

    /etc/init.d/httpd restart

     

    注意确保没有进程占用文件,我删除并重启服务后,由于tail -f /app/logs/access_log也在占用该文件,导致一直没有释放,结束命令后即可。

     

    5. 较好的解决方案

    清空日志而不删除日志。

    /app/logs/access_log

     
     
  • 相关阅读:
    erl_0012 timer:tc 测试模块函数调用运行耗时
    erl_0011 erlang 定时器相关
    erl0010
    erl0009
    erl0008
    erl0007
    erl0006
    erl0005
    开开心心过生活、踏踏实实做技术
    Android-理解Intent
  • 原文地址:https://www.cnblogs.com/zoe233/p/11919778.html
Copyright © 2020-2023  润新知