我使用什么命令查看文件系统中文件的开头和结尾?


10

是否有任何命令可以输出任何文件的开始和结束块?


1
什么文件系统类型:ext2,3,4; btrfs; xfs; zfs等...?
BeowulfNode42 2013年

@ BeowulfNode42:ext4,ntfs,fat32是我经常处理的问题……因此,这三者最好……
精确

这个问题应该改善(更精确):我的第一个答案应该是某个程序打开文件,读取第一个块,然后查找最后一个块,然后再读取。那么什么是块的“输出”?块的内容,块的逻辑地址(文件内部,文件系统内部,分区内部或块设备内部)或块的物理地址(如果磁盘是某些RAID或LVM的一部分,将变得很有趣)。答案似乎比问题要好得多。
U. Windl

Answers:


16

hdparm

我不是100%确定这是您要查找的内容,但我相信您可以使用命令hdparm(特别是使用其--fibmap开关)来执行此操作。

摘抄

   --fibmap
          When  used,  this  must  be the only option given.  It requires a 
          file path as a parameter, and will print out a list of the block 
          extents (sector ranges) occupied by that file on disk.  Sector 
          numbers are  given as absolute LBA numbers, referenced from sector 
          0 of the physical device rather than from the partition or 
          filesystem.  This information can then be used for a variety of 
          purposes,  such  as examining the degree of fragmenation of larger 
          files, or determining appropriate sectors to deliberately corrupt 
          during fault-injection testing procedures.

          This option uses the new FIEMAP (file extent map) ioctl() when 
          available,  and  falls  back  to  the older  FIBMAP (file block 
          map) ioctl() otherwise.  Note that FIBMAP suffers from a 32-bit 
          block-number interface, and thus not work beyond 8TB or 16TB.  
          FIBMAP is also very slow, and  does  not  deal well  with  
          preallocated uncommitted extents in ext4/xfs filesystems, unless a 
          sync() is done before using this option.

说我们有一个样本文件。

$ echo "this is a test file" > afile

现在,当我们跑步时hdparm

$ sudo hdparm --fibmap afile 

afile:
 filesystem blocksize 4096, begins at LBA 0; assuming 512 byte sectors.
 byte_offset  begin_LBA    end_LBA    sectors
           0  282439184  282439191          8

文件片段

找出文件的开始和结束块的另一种不错的方法是filefrag。不过,您需要使用适当的开关才能获得所需的输出。该工具的一个好处hdparm是任何用户都可以运行它,因此sudo不需要。您将需要使用-b512开关,以便以512字节块显示输出。另外,我们需要说filefrag得很详细。

$ filefrag -b512 -v afile
Filesystem type is: ef53
File size of afile is 20 (8 block of 512 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..       7:  282439184.. 282439191:      8:             eof
afile: 1 extent found

调试文件

获取文件的LBA的第三种方法是使用debugfs。这种方法需要一点数学运算,但是我认为debugfs,对于那些可能会感到好奇的人来说,展示如何将其从报告的范围值转换为LBA 至关重要。

因此,让我们从文件的inode开始。

$ ls -i afile
6560281 afile

注意:我们也可以在其中使用文件名,debugfs但是在本演示中,我将使用inode代替。

现在,让我们stat通过debugfs有关我们的inode 的信息。

$ sudo debugfs -R "stat <6560281>" /dev/mapper/fedora_greeneggs-home
debugfs 1.42.7 (21-Jan-2013)
Inode: 6560281   Type: regular    Mode:  0664   Flags: 0x80000
Generation: 1999478298    Version: 0x00000000:00000001
User:  1000   Group:  1000   Size: 20
File ACL: 0    Directory ACL: 0
Links: 1   Blockcount: 8
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x52be10c3:a640e994 -- Fri Dec 27 18:44:03 2013
 atime: 0x52bff8a1:a9f08020 -- Sun Dec 29 05:25:37 2013
 mtime: 0x52be0fe7:18a2f344 -- Fri Dec 27 18:40:23 2013
crtime: 0x52be0dd8:64394b00 -- Fri Dec 27 18:31:36 2013
Size of extra inode fields: 28
Extended attributes stored in inode body: 
  selinux = "unconfined_u:object_r:user_home_t:s0\000" (37)
EXTENTS:
(0):35304898

重要信息在范围部分中。这些实际上是此索引节点正在使用的文件系统块。我们只需要将它们转换为LBA。我们可以通过以下方程式实现。

注意:假设我们的文件系统使用4k块大小,并且底层硬件使用512字节单位,我们需要将exents乘以8。

beginning LBA = (BEGIN EXTENT) * 8
ending LBA    = (((ENDING EXTENT) + 1) * 8) - 1

因此,在我们的示例中,我们的开始和结束范围是相同的,因为我们的文件适合单个范围。

beginning LBA = 35304898 * 8             = 282439184
ending LBA    = ((35304898 + 1) * 8) - 1 = 282439191

因此,我们的LBA为282439184..282439191。

参考文献


这些一些链接...感谢您的回答和链接...
精确

2
@hash-它们是我试图找到另外两种确定LBA的方法的残余。8)。我现在在网站上将其写为我自己的问题。
slm

@hash-我添加了另一种使用的技术filefrag
slm

@hash-我添加了另一种使用的技术debugfs
slm

我尝试filefrag使用1024和2048的可用块大小。debugfs具有较大的文件范围:0-12187 ..我会花点时间来理解..这是一个很大的帮助,谢谢...
精确

4

相对于保存FS的块设备的扇区号(不是整个磁盘)

(请注意,这hdparm --fibmap是相对于整个磁盘,而不是分区或其他任何包含FS的blockdev。它也需要root用户。)

filefrag -e可以很好地运行,并使用通用且高效的FIEMAPioctl,因此它几乎可以在任何文件系统上运行(包括经常使用的BTRFS,甚至对于BTRFS压缩的文件)。对于没有FIEMAP支持的文件系统/内核,它将退回到FIBMAP。

$ filefrag xpsp3.vdi          # some old sparse disk image I had lying around
xpsp3.vdi: 110 extents found
$ filefrag -e xpsp3.vdi
Filesystem type is: 58465342
File size of xpsp3.vdi is 5368730112 (1310726 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..       5: 1322629241..1322629246:      6:            
   1:       13..      13: 1322620799..1322620799:      1: 1322629247:
   2:       15..      47: 1323459271..1323459303:     33: 1322620800:
...
 160:   899498..  915839: 1325792977..1325809318:  16342: 1325725438:
 161:  1307294.. 1307391: 1323938199..1323938296:     98: 1325809319: last
xpsp3.vdi: 110 extents found

仅XFS

如果您使用的是xfs,则xfs_bmap输出更好:它显示了有孔的位置,而filefrag下一个范围则从后面的扇区开始。它使用512B块,而不考虑文件系统实际的块大小。(在Linux上通常为4k)。它显示每个扩展区属于哪个分配组,以及如何在RAID条带边界上对齐。

$ xfs_bmap -vvpl xpsp3.vdi   # the extra -v prints a key to the flags
xpsp3.vdi:
 EXT: FILE-OFFSET           BLOCK-RANGE              AG AG-OFFSET              TOTAL FLAGS
   0: [0..47]:              10581033928..10581033975 13 (83912..83959)            48 01111
   1: [48..103]:            hole                                                  56
   2: [104..111]:           10580966392..10580966399 13 (16376..16383)             8 01010
   3: [112..119]:           hole                                                   8
 ...
 322: [10458352..10459135]: 10591505592..10591506375 13 (10555576..10556359)     784 01111
 323: [10459136..10485807]: hole                                               26672
FLAG Values:   # this part is only here with -vv
    010000 Unwritten preallocated extent
    001000 Doesn't begin on stripe unit
    000100 Doesn't end   on stripe unit
    000010 Doesn't begin on stripe width
    000001 Doesn't end   on stripe width

-l-v使用时是多余的,但是由于某种原因我总是键入-vpl-pl输出更紧凑。


双方filefragxfs_bmap告诉你预分配的程度。

$ fallocate --length $((1024*1024*8)) prealloced_file
$ filefrag -e prealloced_file
Filesystem type is: 58465342
File size of prealloced_file is 8388608 (2048 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..    2047: 1325371648..1325373695:   2048:             last,unwritten,eof
prealloced_file: 1 extent found
$ xfs_bmap -vvpl prealloced_file 
prealloced_file:
 EXT: FILE-OFFSET      BLOCK-RANGE              AG AG-OFFSET            TOTAL FLAGS
   0: [0..16383]:      10602973184..10602989567 13 (22023168..22039551) 16384 10010
 FLAG Values:
    010000 Unwritten preallocated extent
    001000 Doesn't begin on stripe unit
    000100 Doesn't end   on stripe unit
    000010 Doesn't begin on stripe width
    000001 Doesn't end   on stripe width
$ dd if=/dev/zero of=prealloced_file conv=notrunc bs=4k count=10 seek=10000
40960 bytes (41 kB) copied, 0.000335111 s, 122 MB/s
$ xfs_bmap -vpl prealloced_file                                           
prealloced_file:
 EXT: FILE-OFFSET      BLOCK-RANGE              AG AG-OFFSET            TOTAL FLAGS
   0: [0..16383]:      10602973184..10602989567 13 (22023168..22039551) 16384 10010
   1: [16384..79999]:  hole                                             63616
   2: [80000..80895]:  10603013120..10603014015 13 (22063104..22063999)   896 00111
 # oops, wrote past EOF and extended the file, instead of in the middle of the preallocated extent
$ dd if=/dev/zero of=prealloced_file conv=notrunc bs=4k count=10 seek=100
40960 bytes (41 kB) copied, 0.000212986 s, 192 MB/s
$ xfs_bmap -vpl prealloced_file 
prealloced_file:
 EXT: FILE-OFFSET      BLOCK-RANGE              AG AG-OFFSET            TOTAL FLAGS
   0: [0..16383]:      10602973184..10602989567 13 (22023168..22039551) 16384 10010
   1: [16384..79999]:  hole                                             63616
   2: [80000..80895]:  10603013120..10603014015 13 (22063104..22063999)   896 00111
# If you check *right away*, XFS's delayed allocation hasn't happened yet.
# FIEMAP on xfs only reflects allocations, which lag behind completed writes.  fsync first if you need it, IIRC.
$ xfs_bmap -vpl prealloced_file 
prealloced_file:
 EXT: FILE-OFFSET      BLOCK-RANGE              AG AG-OFFSET            TOTAL FLAGS
   0: [0..799]:        10602973184..10602973983 13 (22023168..22023967)   800 10111
   1: [800..879]:      10602973984..10602974063 13 (22023968..22024047)    80 01111
   2: [880..16383]:    10602974064..10602989567 13 (22024048..22039551) 15504 11010
   3: [16384..79999]:  hole                                             63616
   4: [80000..80895]:  10603013120..10603014015 13 (22063104..22063999)   896 00111
$ filefrag -e prealloced_file 
Filesystem type is: 58465342
File size of prealloced_file is 41000960 (10010 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..      99: 1325371648..1325371747:    100:             unwritten
   1:      100..     109: 1325371748..1325371757:     10:            
   2:      110..    2047: 1325371758..1325373695:   1938:             unwritten
   3:    10000..   10111: 1325376640..1325376751:    112: 1325373696: last,eof
prealloced_file: 2 extents found

hdparm --fibmap如果你想有一个扇区号是唯一有用的相对于整个硬盘分区中的文件系统上。它不能在软件RAID(或文件系统和硬盘驱动器之间的任何其他设备)上运行。它也需要root。尽管有该选项的名称,但实际上它会FIEMAP在可用时使用(更新的扩展区映射ioctl,而不是旧的慢速块映射ioctl)。

# hdparm --fibmap ..../xpsp3.vdi
Unable to determine start offset LBA for device, aborting.

0

因此,对于给定的文件,您想知道哪些磁盘块号包含该文件的开头和结尾。

debugfs(8)对于ext2 / 3/4 FS看起来很有希望

stat(1),ls -i,lsof(8)提供了索引节点号,但关于磁盘块的信息不多。

head / tail --bytes = 1024对于文件内容很有用,但对于磁盘块则没有帮助。

dd(1)将是您要检查的块内容-警惕seek =和skip =参数之间的差异,并避免使用of = / dev / ...,除非您确实希望输出文件成为设备。


不,这不是我的意思。。。它是我关注的磁盘的块号。
2013年

0

hdparm --fibmap将列出文件占用的块。请注意,它们可能不是连续的,因此“开始和结束”没有意义。


我认为您所指的开关是--fibmap。另外,您需要指定一个文件名w /它。范例:hdparm --fibmap afile
slm

@slm,哎呀,是的,错别字...而且我认为很明显,您必须命名有问题的文件。
psusi 2013年

直到我尝试运行它时,这才对我而言。直到今天,我过去的经验hdparm都涉及整个驱动器级别,以前从未将其用于文件。
slm
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.