ext4에서 출생이 비어 있습니다


83

방금 Birth섹션을 읽고 있었고 statext4가 지원 해야하는 것처럼 보이지만 방금 만든 파일조차도 비워 둡니다.

 ~  % 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파티션이이 필드를 채우지 않는 이유는 무엇 입니까?

답변:


93

필드가 채워지고 (아래 참조) 필드 만 coreutils stat표시되지 않습니다. 분명히 그들은 기다리고있어 1 위한 xstat()인터페이스 .

coreutils 패치-8 월. 2012-TODO

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

LKML 스레드 에 대한 1 Linus의 답변


7
@ Sparhawk : 별도의 파티션에 /home/user/path/to/file있기 때문에 파일 에이 문제가 있습니다 /home. 이 경우 제공된 경로는에 stat상대적이어야합니다 /home. 예 : sudo debugfs -R 'stat user/path/to/file' /dev/sda2. 경로 처리를 없애기 위해 경로 stat대신 inode 번호를 제공 할 수 있습니다 .sudo debugfs -R "stat <$(stat -c %i /home/user/path/to/file)>" /dev/sda5
jpfleury

3
네트워크 마운트 파일 시스템에서 파일 작성 시간을 얻는 데 사용할 수 있습니까?
taranaki

1
따라서 이것은 파일 시스템 생성을 넘어서는 타임 스탬프가 아닙니다. 그것은 25 년 전에 파일이 생성되어 많은 다른 물리적 또는 마운트 된 시스템을 통해 복사 된 경우 메타 데이터에서 생성 날짜 정보를 찾을 수있는 방법이 전혀 없다는 것을 의미합니까? 파일이 언제 만들어 졌는지 알 수있는 유일한 방법은 파일 이름으로 파일을 입력하는 것입니까? 아니면 내용 안에? 이 겉보기에 이상한 비 구현의 이유가 있습니까?
sinekonata

2
@sinekonata 파일 메타 데이터는 시스템에 매우 의존적이며 (이 답변에 나와있는 것처럼 OS의 모든 계층에서이를 처리 할 수 ​​있어야 함) 여러 시스템간에 복사본을 유지하려면 시스템 복사 도구가 해당 메타 데이터 형식을 지원해야합니다 . 이것이 의미하는 바는 파일 이름이 엉킴이 아니라면 운이 좋다는 것입니다. 또는 일부 파일 형식을 사용하면 파일 내에 메타 데이터 (예 : ID3 ) 를 삽입 할 수 있으며 일반적으로 잘 전달되지만 많은 형식에는 이러한 기능이 없습니다. 마지막으로 다음과 같은 아카이브 파일에 파일을 넣을 수 있습니다.
André Paramés

1
점을 유의 <>inode 번호 주위가 필요합니다. 이들은 종종 조정되어야하는 변수를 둘러싸 기 위해 예제에서 사용되지만이 경우에는 문자 그대로 입력해야합니다. 그것들이 없으면 inode 번호는 경로로 취급되며 File not found by ext2_lookup오류가 발생합니다.
mivk

31

이것을 간단한 쉘 함수로 결합했습니다.

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호출은 나중에 제안되었다 , 그리고 한 리눅스 4.11에 합병 . 새로운 statx(2)시스템 호출은 생성 시간을 반환 구조체에 포함시킵니다. 래퍼 statx(2)2.28 (2018 년 8 월 릴리스) 에서만 glibc에 추가되었습니다 . 이 래퍼 사용에 대한 지원은 GNU coreutils 8.31 (2019 년 3 월 릴리스) 에 추가되었습니다 .

stat는 glibc> = 2.28이고 kernel> = 4.11 인 GNU Linux 시스템에서 파일 시스템이 지원할 때 파일 작성 시간을 인쇄합니다.

% 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

다음은 statxuserland가 아직 따라 잡지 않은 곳 (이전 glibc 또는 coreutils) 의 데모입니다 . C 프로그램에서 직접 시스템 호출을 호출하는 것은 쉽지 않습니다. 일반적으로 glibc는 작업을 쉽게하는 래퍼를 제공하지만, 다행히 @whotwagner는 x86 및 x86-64 시스템 에서 시스템 호출 을 사용하는 방법을 보여주는 샘플 C 프로그램 을 작성 했습니다statx(2) . 출력 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 * 파일 시스템보다 더 많은 파일 시스템에서 액세스 할 수 있도록해야합니다 ( debugfsext2 / 3 / 4 파일 시스템 용 도구이며 다른 시스템에서는 사용할 수 없음). XFS 시스템에서는 작동했지만 NTFS 및 exfat에서는 작동하지 않았습니다. 나는 그것들을위한 FUSE 파일 시스템이 생성 시간을 포함하지 않았다고 생각한다.


5

출생 시간이 비어 있거나 0 / 대시 인 또 다른 경우가 있습니다. Ext4의 Inode 크기는 저장하려면 256 바이트 이상이어야 crtime합니다. 처음 512MB보다 작은 파일 시스템을 만든 경우이 문제가 발생합니다 (기본 Inode 크기는 128 바이트입니다. 참조 /etc/mke2fs.confmkfs.ext4맨 페이지).

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

그리고 / 또는

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

이제 파일 시스템 inode를 확인하십시오 (저장하기에 충분히 큰 crtime가요?) :

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

기술 정보 : Ext4 디스크 레이아웃 페이지에서 inode 테이블의 일부 속성이 0x80 (128)을 초과합니다.


맞습니다 ( vger에서 이것에 대해 읽은 것을 기억합니다 ). 512MB 제한은 1275mke2fs.c 행에 정의되어 있습니다 .
don_crissti

2

그만한 가치가 있기 때문에 나는 pedantic을 느꼈기 때문에 stat 주위에 bash 래퍼를 작성하여 debugfs를 사용하여 crtime을 자동으로 지원하여 가능한 경우 기본 ext4 파일 시스템에서 가져옵니다. 나는 그것이 강력하기를 바랍니다. 여기에서 찾으십시오 .

해당 스크립트에 설명 된대로 Linux의 할 일 목록에 수정 사항이있을 수 있습니다. 따라서이 래퍼는 그것이 끝날 때까지 공칭 수명을 가지며 가능한 일에서 더 많은 운동입니다.


3
참고 xstat()는 GNU libc의 시간 문제이고, 그래서 결국, 리눅스에 추가되었습니다 find에 대한 지원을 추가합니다.
Stéphane Chazelas

1
대박! 참 좋은 소식입니다.
Bernd Wechner 2016 년

6
pedantic에 대한 사과와 함께, 당신은 "pedantic"의 의미를 이해하지 못하는 것 같습니다.
Nick

"세부 사항이나 형식주의에 지나치게 관심이있다"-받아 들여진 대답은 괜찮지 만 공식화하자. ;-)
Bernd Wechner
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.