• 什么是“稀疏文件”("sparse file"),可以识别它们吗?


    环境

    • 红帽企业版Linux 5、6和7

    问题

    • 文件的ls和df之间的文件大小不一致。
    • 该文件报告较大(128Gb),但文件系统甚至没有那么大。这怎么可能?

      # ls -lah datafile
       -rw------- 1 root root 137438953440 May 28 10:05 datafile 
      
      # df -h 
      Filesystem Size Used Avail Use% Mounted on 
      /dev/sda     20G 9.8G 9.0G 53%     /         

    决议

    • 有问题的文件可能是稀疏文件
    • 稀疏文件是指其元数据报告一个大小的文件,但是文件的实际数据消耗的大小不同。
    • 稀疏文件是有效使用磁盘空间的常用方法。
    • 您可以使用ls -lsh命令查看稀疏文件。这提供了两个大小列:

      $ ls -lsh datafile
       12G -rw-r----- 1 root root 24G 2010-01-10 19:55 data 
       ^ - - - - - - - - - - - - - ^ 
    • 第一列是实际使用的磁盘空间。该文件实际上消耗了12Gb的空间。

    • 第二个大小列提供文件元数据的大小。该文件的元数据报告它是24Gb文件。

    稀疏文件的使用

    • 要复制稀疏文件,必须使用能够识别稀疏文件的命令。

    •     cp --sparse=always /source/filename /destination/filename
          dd if=/source/filename of=/destination/filename conv=sparse
          rsync -S /source/filename root@hostname:/destination/filename
    • 使用scp实用程序复制文件将导致“非稀疏”文件扩展为完整大小。

    根本原因

    • 在稀疏文件中,与那些区域保存非零数据时相比,文件全为0x00的部分被压缩以占用更少的空间。

    诊断步骤

    可以使用truncate命令轻松创建稀疏文件:

     
    # truncate --size=1G sparsefile.bin 

    我们可以使用ls -lsh查看稀疏文件的大小:

     
    # ls -lsh sparsefile.bin 
    0 -rw-r--r-- 1 root root 1.0G Nov 6 09:00 sparsefile.bin 

    该文件占用0字节的空间,但是其元数据报告文件大小为1Gb。

    我们可以将1Mb写入该文件:

     
    # for i in {1..1048576}; do echo -n "a" >> sparsefile.bin; done 

    然后再次检查其大小:

     
     # ls -lsh sparsefile.bin 
    1.0M -rw-r--r-- 1 root root 1.1G Nov 6 09:01 sparsefile.bin

    该文件现在消耗了1Mb的实际空间,但是元数据报告的使用量为1.1Gb。元数据的轻微增长是由于分配了文件系统块来存储文件的数据。

    将此文件与相同大小的完全分配的文件进行比较:

     
     # dd if=/dev/zero of=fullfile.bin bs=1M count=1024 conv=fsync 
    # ls -lsh fullfile.bin 
    1.1G -rw-r--r-- 1 root root 1.0G Nov 6 09:05 fullfile.bin 

    该文件实际消耗了1Gb以上的空间,其元数据报告的文件大小也为1Gb。

    我们可以使用stat命令从这两个文件中获取更多信息:

    # stat sparsefile.bin
     File: `sparsefile.bin'
     Size: 1074790400 Blocks: 2048 IO Block: 4096 regular file 
    Device: fd00h/64768d Inode: 134154 Links: 1 
    Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root) 
    
    # stat fullfile.bin
     File: `fullfile.bin'
     Size: 1048576000 Blocks: 2048008 IO Block: 4096 regular file 
    Device: fd00h/64768d Inode: 134403 Links: 1 
    Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root) 

    在上方,我们看到稀疏文件比完整文件消耗更少的文件系统块。

    我们可以使用filefrag命令收集文件系统分配信息:

     
    # filefrag sparsefile.bin 
    sparsefile.bin: 1 extent found

    # filefrag fullfile.bin
    fullfile.bin: 29 extents found

    上面我们可以看到,稀疏文件已在一个较小的范围内分配,而完整文件已在多个范围内分配。

    可以使用以下基本示例在C中创造稀疏文件:

    #include <stdio.h>
    
    int main() {
        FILE *fp;
    
        fp = fopen("hello.txt", "w+");
        fseek(fp, 1048576, SEEK_CUR);
        fputs("Hello
    ", fp);
        fclose(fp);
    
        return 0;
    }

    这将创建一个1 MB的文件,放入“ Hello”写入其中。在strace系统调用跟踪器下运行以上命令显示:

    09:00:20 open("hello.txt", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3 <0.000056>
    09:00:20 fstat(3, {st_dev=makedev(253, 2), st_ino=20188301, st_mode=S_IFREG|0664, st_nlink=1, st_uid=1000, st_gid=1000, st_blksize=4096, st_blocks=0, st_size=0, st_atime=2014/11/08-09:00:20, st_mtime=2014/11/08-09:00:20, st_ctime=2014/11/08-09:00:20}) = 0 <0.000005>
    09:00:20 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f469d042000 <0.000007>
    09:00:20 lseek(3, 1048576, SEEK_CUR)    = 1048576 <0.000005>
    09:00:20 write(3, "Hello
    ", 6)         = 6 <0.000018>
    09:00:20 close(3)                       = 0 <0.000006>

    我们可以看到我们的文件是稀疏创建的,它报告的大小为1Mb,但仅消耗一个4kb的文件系统块:

    $ ls -ls hello.txt 
    4 -rw-rw-r--. 1 username username 1048582 Nov  8 09:00 hello.txt
    
    
  • 相关阅读:
    BUUCTF | [极客大挑战 2019]PHP
    BUUCTF | [极客大挑战 2019]Secret File
    [网鼎杯 2018] Fakebook 复现
    [强网杯2019 随便注]总结
    [Flask(Jinja2)服务端模板注入漏洞(SSTI)]学习简记
    [Flask框架]学习简记
    ADO.NET基础
    SQL Server基础
    AdventureWorks2012下载链接
    SQL Server2012从入门到精通
  • 原文地址:https://www.cnblogs.com/augusite/p/14138554.html
Copyright © 2020-2023  润新知