ext4上的出生是空的


83

我只是在阅读的Birth部分,stat似乎ext4应该支持它,但是即使是我刚刚创建的文件也将其保留为空。

 ~  % touch test                                                       slave-iv
 ~  % stat test.pl                                                     slave-iv
  File: ‘test.pl’
  Size: 173             Blocks: 8          IO Block: 4096   regular file
Device: 903h/2307d      Inode: 41943086    Links: 1
Access: (0600/-rw-------)  Uid: ( 1000/xenoterracide)   Gid: (  100/   users)
Access: 2012-09-22 18:22:16.924634497 -0500
Modify: 2012-09-22 18:22:16.924634497 -0500
Change: 2012-09-22 18:22:16.947967935 -0500
 Birth: -

 ~  % sudo tune2fs -l /dev/md3 | psp4                                  slave-iv
tune2fs 1.42.5 (29-Jul-2012)
Filesystem volume name:   home
Last mounted on:          /home
Filesystem UUID:          ab2e39fb-acdd-416a-9e10-b501498056de
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal ext_attr resize_inode dir_index 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:    journal_data
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              59736064
Block count:              238920960
Reserved block count:     11946048
Free blocks:              34486248
Free inodes:              59610013
First block:              0
Block size:               4096
Fragment size:            4096
Reserved GDT blocks:      967
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         8192
Inode blocks per group:   512
RAID stride:              128
RAID stripe width:        256
Flex block group size:    16
Filesystem created:       Mon May 31 20:36:30 2010
Last mount time:          Sat Oct  6 11:01:01 2012
Last write time:          Sat Oct  6 11:01:01 2012
Mount count:              14
Maximum mount count:      34
Last checked:             Tue Jul 10 08:26:37 2012
Check interval:           15552000 (6 months)
Next check after:         Sun Jan  6 07:26:37 2013
Lifetime writes:          7255 GB
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:           256
Required extra isize:     28
Desired extra isize:      28
Journal inode:            8
First orphan inode:       55313243
Default directory hash:   half_md4
Directory Hash Seed:      442c66e8-8b67-4a8c-92a6-2e2d0c220044
Journal backup:           inode blocks

为什么我的ext4分区没有填充此字段?

Answers:


93

仅填充该字段(请参见下文)coreutils stat而不显示它。显然,他们正在等待1xstat()接口

coreutils补丁-8月。2012-待办事项

stat(1)和ls(1)支持出生时间。取决于内核提供的xstat()

您可以通过debugfs以下方式获取创建时间:

debugfs -R 'stat <inode_number>' DEVICE

例如,对于我/etc/profile所在的设备/dev/sda2(请参阅如何找出文件所在的设备):

stat -c%i / etc / profile
398264
debugfs -R 'stat <398264>' /dev/sda2
debugfs 1.42.5 (29-Jul-2012)
Inode: 398264   Type: regular    Mode:  0644   Flags: 0x80000
Generation: 2058737571    Version: 0x00000000:00000001
User:     0   Group:     0   Size: 562
File ACL: 0    Directory ACL: 0
Links: 1   Blockcount: 8
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x506b860b:19fa3c34 -- Wed Oct  3 02:25:47 2012
 atime: 0x50476677:dcd84978 -- Wed Sep  5 16:49:27 2012
 mtime: 0x506b860b:19fa3c34 -- Wed Oct  3 02:25:47 2012
crtime: 0x50476677:dcd84978 -- Wed Sep  5 16:49:27 2012
Size of extra inode fields: 28
EXTENTS:
(0):3308774

1 Linus对LKML 线程的回复


7
@Sparhawk:我的文件也有这个问题,/home/user/path/to/file因为/home它位于单独的分区上。在这种情况下,提供给的路径stat必须相对于/home。范例:sudo debugfs -R 'stat user/path/to/file' /dev/sda2。为了摆脱路径处理,我们可以提供statsudo debugfs -R "stat <$(stat -c %i /home/user/path/to/file)>" /dev/sda5
索引

3
可以用来从网络安装的文件系统中获取文件的创建时间吗?
taranaki

1
因此,这不是创建文件系统之外的时间戳。这意味着,如果文件是25年前创建的,并且通过许多不同的物理或安装的系统进行复制,则根本无法在任何元数据中找到创建日期的信息吗?因此,知道何时创建文件的唯一方法是将其键入文件名?还是里面的内容?这种看似奇怪的未实现是否有任何原因?
sinekonata

2
@sinekonata文件元数据非常依赖于系统(如该答案所示,操作系统的每一层都必须能够处理它),并且在计算机之间的跨副本中保持它依赖于系统复制工具对该元数据格式的支持。这意味着:如果您没有弄乱文件名,那么您将很幸运。或者,某些文件格式允许您在文件插入元数据(例如ID3),并且通常携带良好,但是许多格式不具备此功能。最后,你可以把文件就像一个压缩文件里
安德烈Paramés

1
需要注意的是,<>周围的inode编号是必需的。在示例中,它们通常用于包围应调整的变量,但是在这种情况下,必须按字面值输入。没有它们,inode编号将被视为路径,并且会出现File not found by ext2_lookup错误。
mivk

31

我将其组合成一个简单的shell函数:

get_crtime() {
  for target in "${@}"; do
    inode=$(stat -c %i "${target}")
    fs=$(df  --output=source "${target}"  | tail -1)
    crtime=$(sudo debugfs -R 'stat <'"${inode}"'>' "${fs}" 2>/dev/null | 
    grep -oP 'crtime.*--\s*\K.*')
    printf "%s\t%s\n" "${target}" "${crtime}"
  done
    }

然后,您可以使用

$ get_crtime foo foo/file /etc/
foo Wed May 21 17:11:08 2014
foo/file    Wed May 21 17:11:27 2014
/etc/   Wed Aug  1 20:42:03 2012

22

xstat功能从未合并到主线中。但是,statx稍后提出了一个新的调用,该调用已在Linux 4.11合并。新的statx(2)系统调用的返回结构中确实包含创建时间。statx(2)仅在2.28(发布于2018年8月)中将包装器添加到glibc中。在GNU coreutils 8.31(于2019年3月发布)中添加了对使用此包装器的支持:

在文件系统支持的情况下,在glibc> = 2.28和内核> = 4.11的GNU Linux系统上,stat现在可以打印文件创建时间。

% stat --version
stat (GNU coreutils) 8.31
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Michael Meskes.
% stat /
  File: /
  Size: 4096            Blocks: 8          IO Block: 4096   directory
Device: b302h/45826d    Inode: 2           Links: 17
Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2019-06-06 20:03:12.898725626 +0900
Modify: 2019-05-28 05:15:44.452651395 +0900
Change: 2019-05-28 05:15:44.452651395 +0900
 Birth: 2018-06-07 20:35:54.000000000 +0900

接下来是演示statx用户级尚未赶上的地方(旧的glibc或coreutils)。直接在C程序中调用系统调用并不容易。通常,glibc提供了一个使工作变得容易的包装器,但是幸运的是,@ whotwagner编写了一个示例C程序,该程序演示了如何statx(2)在x86和x86-64系统上使用系统调用。其输出格式与stat默认格式相同,没有任何格式设置选项,但修改它以仅打印出生时间很简单。(如果您有足够新的glibc,则不需要它-您可以statx按照所述直接使用man 2 statx)。

首先,克隆它:

git clone https://github.com/whotwagner/statx-fun

您可以编译statx.c代码,或者,如果只想知道出生时间,请birth.c使用以下代码在克隆的目录中创建一个(这是statx.c打印仅包含创建时间时间戳(包括纳秒精度)的最小版本):

#define _GNU_SOURCE
#define _ATFILE_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include "statx.h"
#include <time.h>
#include <getopt.h>
#include <string.h>

// does not (yet) provide a wrapper for the statx() system call
#include <sys/syscall.h>

/* this code works ony with x86 and x86_64 */
#if __x86_64__
#define __NR_statx 332
#else
#define __NR_statx 383
#endif

#define statx(a,b,c,d,e) syscall(__NR_statx,(a),(b),(c),(d),(e))

int main(int argc, char *argv[])
{
    int dirfd = AT_FDCWD;
    int flags = AT_SYMLINK_NOFOLLOW;
    unsigned int mask = STATX_ALL;
    struct statx stxbuf;
    long ret = 0;

    int opt = 0;

    while(( opt = getopt(argc, argv, "alfd")) != -1)
    {
        switch(opt) {
            case 'a':
                flags |= AT_NO_AUTOMOUNT;
                break;
            case 'l':
                flags &= ~AT_SYMLINK_NOFOLLOW;
                break;
            case 'f':
                flags &= ~AT_STATX_SYNC_TYPE;
                flags |= AT_STATX_FORCE_SYNC;
                break;
            case 'd':
                flags &= ~AT_STATX_SYNC_TYPE;
                flags |= AT_STATX_DONT_SYNC;
                break;
            default:
                exit(EXIT_SUCCESS);
                break;
        }
    }

    if (optind >= argc) {
        exit(EXIT_FAILURE);
    }

    for (; optind < argc; optind++) {
        memset(&stxbuf, 0xbf, sizeof(stxbuf));
        ret = statx(dirfd, argv[optind], flags, mask, &stxbuf);
        if( ret < 0)
        {
            perror("statx");
            return EXIT_FAILURE;
        }
        printf("%lld.%u\n", *&stxbuf.stx_btime.tv_sec, *&stxbuf.stx_btime.tv_nsec);
    }
    return EXIT_SUCCESS;
}

然后:

$ make birth
$ ./birth ./birth.c
1511793291.254337149
$ ./birth ./birth.c | xargs -I {} date -d @{}
Mon Nov 27 14:34:51 UTC 2017

从理论上讲,这应该使创建时间可以在更多文件系统上访问,而不仅仅是ext *文件系统(这debugfs是ext2 / 3/4文件系统的工具,而在其他文件系统上则不可用)。它确实适用于XFS系统,但不适用于NTFS和exfat。我猜那些的FUSE文件系统不包括创建时间。


5

还有另一种情况,出生时间将为空/零/破折号:Ext4的Inode大小必须至少为256bytes才能存储crtime。如果最初创建的文件系统小于512MB(默认的Inode大小为128字节,请参见/etc/mke2fs.confmkfs.ext4联机帮助页),则会出现问题。

stat -c '%n: %w' testfile
testfile: -  

和/或

stat -c '%n: %W' testfile
testfile: 0

现在检查文件系统索引节点(它是否足以存储crtime?):

tune2fs -l $(df . --output=source | grep ^/) | grep "Inode size:"
Inode size:           128

技术信息:在Ext4磁盘布局页面上,请注意inode表的某些属性超出0x80(128)。


正确(我记得在vger上阅读过此内容)。512MB的限制mke2fs.c在第1275
don_crissti

2

对于我值得的东西,我感到很痴迷,于是在stat周围写了一个bash包装器,以使用debugfs从底层ext4文件系统中获取它来默默支持crtime。我希望它坚固。在这里找到它

请注意,表面上该脚本上记录了Linux的待办事项列表上的修复程序。因此,此包装器只有在完成此操作后才有标称的使用寿命,而更多的是在可行范围内的练习。


3
请注意,xstat()它最终已添加到Linux中,因此GNU libc find为其添加支持只是时间问题。
斯特凡Chazelas

1
太棒了!确实是个好消息。
伯纳德·韦奇纳

6
出于道歉的态度,您似乎无法理解“ pedantic”的含义。
尼克

“过分关注细节或形式主义”-例如,可以接受的答案很好,但是...让我们对其进行形式化。;-)
Bernd Wechner
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.