确定排序列表中的多少个文件将填满磁盘

确定排序列表中的多少个文件将填满磁盘

这让我很疑惑。我认为这应该很容易,但我一定错过了一些东西,因为结果并不一致。

我使用 rsync 将一长串文件备份到多个磁盘,使用按时间顺序排序的列表,以便最早的文件位于第一个磁盘上,较晚的文件位于第二个磁盘上,依此类推。

我浏览列表,将文件大小(以 4k 块为单位)相加,并记下最后一个适合的文件的日期。然后我使用“find -not -newer 和 -newer”创建一个列表

STARTDATE="-newer /tmp/filedate.1"
ENDDATE="-not -newer /tmp/filedate.2"
find $SRC -type f ${STARTDATE} ${ENDDATE} -printf '%P\n' | sort > ${TEMPFILE}

并使用“--files-from”将其提供给 rsync 以实际进行复制。

rsync -a --progress --verbose --prune-empty-dirs --files-from=${TEMPFILE} ${SRC} ${TARGET}

我想准确地找出文件的分割位置,以便磁盘已满。

我现在拥有的:

#%T is the modification time, @ is seconds, 
#%p is the path less the command line part, and %k is disk usage in 1k blocks
#MAXSIZE is number of 4k blocks available on disk
    find $SRC -printf "%T@\t%p\t%k\n" | sort -n | \
    awk -vMS="$MAXSIZE"  '
      BEGIN { FS = "\t";fnumber = 0 }
      {rtot+=int(($3+3)/4); #edit; changed to ceiling on AlexP's advice
       if (rtot<MS) {final=$2;filesize=rtot;}
       else {
            rtot=int(($3+3)/4); #edit; changed to ceiling on AlexP's advice
            fnumber++;
            printf "touch -r \"%s\" /tmp/filedate.%s\n", final, fnumber | "/bin/sh"
            print "Found point " fnumber ". (" final ") 4096 Blocks:"  filesize " Space Left:" (MS-filesize)*4
            }
      }
    '

磁盘详细信息是:

    #tune2fs -l /dev/sdzc1
    tune2fs 1.41.4 (27-Jan-2009)
    Filesystem volume name:   <none>
    Last mounted on:          /share/external/sdzc1
    Filesystem UUID:          f3f2e855-b198-4d47-b76f-6526d16b0820
    Filesystem magic number:  0xEF53
    Filesystem revision #:    1 (dynamic)
    Filesystem features:      has_journal ext_attr resize_inode filetype needs_recovery extent flex_bg sparse_super large_file
huge_file uninit_bg dir_nlink extra_isize
    Filesystem flags:         signed_directory_hash
    Default mount options:    (none)
    Filesystem state:         clean
    Errors behavior:          Continue
    Filesystem OS type:       Linux
    Inode count:              122101760
    Block count:              488378007
    Reserved block count:     0
    Free blocks:              89451
    Free inodes:              122088914
    First block:              0
    Block size:               4096
    Fragment size:            4096
    Reserved GDT blocks:      907
    Blocks per group:         32768
    Fragments per group:      32768
    Inodes per group:         8192
    Inode blocks per group:   512
    Flex block group size:    16
    Filesystem created:       Sun May 11 13:45:08 2014
    Last mount time:          Wed Dec  7 11:44:24 2016
    Last write time:          Wed Dec  7 11:44:24 2016
    Mount count:              68
    Maximum mount count:      28
    Last checked:             Fri Feb 20 02:06:42 2015
    Check interval:           15552000 (6 months)
    Next check after:         Wed Aug 19 02:06:42 2015
    Reserved blocks uid:      0 (user admin)
    Reserved blocks gid:      0 (group administrators)
    First inode:              11
    Inode size:               256
    Required extra isize:     28
    Desired extra isize:      28
    Journal inode:            8
    First orphan inode:       75890825
    Default directory hash:   half_md4
    Directory Hash Seed:      1c7f838c-8614-4af0-8506-cd3659e1e5ac
    Directory Magic Number:   0x514E4150
    Journal backup:           inode blocks

所以,根据我的想法,有 488378007 个 4096 字节的块,以及 122101760 个 256 字节的 inode。因此,应该有 (488378007 x 4096) - (122101760 x 256) 字节可供写入。即 1,969,138,264,064,即 1,922,986,586 kB。

df 显示总共 1,922,858,380 个 1k 块(128,206 差异)= 480,714,595 4k 块。

不考虑这一点,最终结果是,当我实际复制文件时,即使使用下图作为起点,awk 输出报告的“剩余空间”也不等于实际剩余空间,通过数量不同,有时甚至完全耗尽空间。

我哪里逻辑出了问题?我知道我可以通过减少 MAXSIZE 来捏造它,但我真的很想了解我错过了什么!

附注我以 root 身份运行它,因此保留空间不相关。

只是为了澄清实际问题:我是否应该能够对文件和目录大小(整个 4k 块)进行求和以获得总磁盘使用量?

附加编辑:只是为了进一步混淆我刚刚填满了(?)一个驱动器并从 df -k 中得到了这个:

Filesystem      1K-blocks       Used Available Use% Mounted on
/dev/sdzb1     2927209048 2925317912         0 100% /share/external/sdzb1

2927209048-2925317912=1891136,还是我上学的时候用过的!

答案1

两个观察结果:

  • 您需要向上舍入文件使用的块数,而不是向下舍入;如果文件的长度为 8192+1 字节,则最后一个字节将分配一个 4 KiB 块。 (因为“片段大小”是 4 KiB。)

  • 文件所需的磁盘空间不一定等于保存文件中字节数所需的数据块数。它可以稍大一点(对于需要更多元数据来映射其分配的块的较大文件),也可以稍小一点(对于非常小的文件,可以完全存储在其 inode 中)。另外,正如用户 Stephen Kitt 提到的,整个问题是稀疏文件,其大小可能比它们在磁盘上占用的空间大得多,并且在存档或复制到不同的文件系统时可能会导致有趣的问题。

  • 某些文件系统可能会出于自己的目的使用一些磁盘空间。此外,当使用的磁盘空间接近容量时,文件系统往往会出现故障。您确实应该计划将磁盘填充率不要超过 98% 或 99%。

答案2

我将回答我自己的问题,感谢所有贡献并指导我思想的人:

由于写入磁盘时分配空间的方式取决于文件大小和类型、稀疏文件等,因此实际上很难(如果不是不可能的话)提前准确预测将占用多少空间。

已删除文件的目录可能比首次创建时更大,并且此空间将无法恢复。 (除非该目录被删除并重新创建)空目录占用空间。

除非特别要求,否则“查找”不会报告目录。

空间以完整块写入,块大小可能因磁盘而异,并且可以从 e2fsdump 读取。

'df' 在大约 98% 后报告没有可用空间,即使它报告的已用块少于可用空间:

# df -B4k --sync
Filesystem      4K-blocks       Used Available Use% Mounted on
/dev/sdzb1      731802262  731493169         0 100% /share/external/sdzb1
/dev/sdzc1      731802262  717225328         0 100% /share/external/sdzc1

'du' 报告与 'df' 不同的用法:

# du -B4k -s /share/external/sdzb1 /share/external/sdzc1
731441722       /share/external/sdzb1
717173881       /share/external/sdzc1

尽管如此,使用可用空间的初始起点是可能的:

Space = (Total blocks x blocksize) - (Total inodes x inode size)

并允许 300,000 到 500,000 块余量,以获得相当准确的结果。 (约1%以内)

相关内容