Sinh trống trên ext4


83

Tôi mới đọc Birthphần này statvà có vẻ như ext4 sẽ hỗ trợ nó, nhưng ngay cả một tệp tôi vừa tạo cũng để trống.

 ~  % 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

Tại sao ext4phân vùng của tôi không điền vào trường này?

Câu trả lời:


93

Trường được điền (xem bên dưới) chỉ coreutils statkhông hiển thị nó. Rõ ràng họ đang chờ đợi 1 cho xstat()giao diện .

bản vá lõi - aug. 2012 - HÔM NAY

stat (1) và ls (1) hỗ trợ cho thời gian sinh. Phụ thuộc vào xstat () được cung cấp bởi kernel

Bạn có thể có được thời gian tạo thông qua debugfs:

debugfs -R 'stat <inode_number>' DEVICE

ví dụ: đối với tôi /etc/profileđang bật /dev/sda2(xem Cách tìm hiểu tập tin đang bật trên thiết bị nào ):

stat -c% i / etc / hồ sơ
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

Trả lời của 1 Linus về chủ đề LKML


7
@Sparhawk: Tôi cũng gặp vấn đề này với một tệp /home/user/path/to/file/homenằm trên một phân vùng riêng. Trong trường hợp đó, đường dẫn được cung cấp statphải liên quan đến /home. Ví dụ : sudo debugfs -R 'stat user/path/to/file' /dev/sda2. Để thoát khỏi việc xử lý đường dẫn, chúng ta có thể cung cấp cho statsố inode thay vì đường dẫn:sudo debugfs -R "stat <$(stat -c %i /home/user/path/to/file)>" /dev/sda5
jpfleury

3
Điều này có thể được sử dụng để có được thời gian tạo tập tin từ hệ thống tập tin gắn trên mạng không?
taranaki

1
Vì vậy, đây không phải là một dấu ấn thời gian vượt ra ngoài việc tạo ra hệ thống tập tin. Điều đó có nghĩa là nếu một tệp được tạo 25 năm trước và được sao chép qua nhiều hệ thống vật lý hoặc gắn kết khác nhau, không có cách nào để tìm thông tin về ngày tạo trong bất kỳ siêu dữ liệu nào? Vì vậy, cách duy nhất để biết khi nào một tập tin được thực hiện là nhập nó vào tên tập tin? Hay bên trong nội dung? Có bất kỳ lý do cho việc không thực hiện dường như kỳ lạ này?
sinekonata

2
Siêu dữ liệu tệp @sinekonata phụ thuộc rất nhiều vào hệ thống (vì câu trả lời này cho thấy, mọi lớp của HĐH phải có khả năng xử lý nó) và giữ nó trên các bản sao giữa các máy phụ thuộc vào sự hỗ trợ cho định dạng siêu dữ liệu đó bởi cả hai hệ thống công cụ sao chép. Điều này có nghĩa là: bạn may mắn nếu bạn thậm chí không nhận được tên tệp không bị xáo trộn. Ngoài ra, một số định dạng tệp cho phép bạn chèn siêu dữ liệu vào trong tệp (ví dụ: ID3 ) và thường mang tốt, nhưng nhiều định dạng không có tính năng như vậy. Cuối cùng, bạn có thể đặt tệp bên trong tệp lưu trữ như
André Paramés

1
Lưu ý rằng <>xung quanh số inode là bắt buộc. Chúng thường được sử dụng trong các ví dụ để bao quanh một biến cần được điều chỉnh, nhưng trong trường hợp này chúng phải được nhập theo nghĩa đen. Không có chúng, số inode được coi là một đường dẫn và bạn gặp File not found by ext2_lookuplỗi.
mivk

31

Tôi đã kết hợp điều này thành một hàm shell đơn giản:

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
    }

Sau đó bạn có thể chạy nó với

$ 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

Các xstatchức năng không bao giờ được sáp nhập vào dòng chính. Tuy nhiên, một statxcuộc gọi mới đã được đề xuất sau đó và được hợp nhất trong Linux 4.11 . Cuộc statx(2)gọi hệ thống mới không bao gồm thời gian tạo trong cấu trúc trả về của nó. Một trình bao bọc cho statx(2)đã được thêm vào glibc chỉ trong 2.28 (phát hành tháng 8 năm 2018) . Và hỗ trợ cho việc sử dụng trình bao bọc này đã được thêm vào trong GNU coreutils 8.31 (phát hành tháng 3 năm 2019):

Hiện tại, in thời gian tạo tệp khi được hệ thống tệp hỗ trợ, trên các hệ thống GNU Linux có glibc> = 2.28 và kernel> = 4.11.

% 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

Phần tiếp theo là bản demo về statxnơi người dùng chưa bắt kịp (glibc hoặc coreutils cũ hơn). Thật không dễ dàng để gọi các cuộc gọi hệ thống trực tiếp trong một chương trình C. Thông thường, glibc cung cấp trình bao bọc giúp công việc trở nên dễ dàng, nhưng May mắn thay, @whotwagner đã viết một chương trình C mẫu cho biết cách sử dụng lệnh statx(2)gọi hệ thống trên các hệ thống x86 và x86-64. Đầu ra của nó có cùng định dạng với statmặc định, không có bất kỳ tùy chọn định dạng nào, nhưng thật đơn giản để sửa đổi nó để chỉ in thời gian sinh. (Nếu bạn có một glibc đủ mới, bạn sẽ không cần điều này - bạn có thể sử dụng statxtrực tiếp như được mô tả trong man 2 statx).

Đầu tiên, sao chép nó:

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

Bạn có thể biên dịch statx.cmã, hoặc, nếu bạn chỉ muốn thời gian sinh, hãy tạo một birth.ctrong thư mục nhân bản với mã sau (đây là phiên bản tối thiểu của statx.cviệc in chỉ dấu thời gian tạo bao gồm độ chính xác nano giây)

#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;
}

Sau đó:

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

Về lý thuyết, điều này sẽ làm cho thời gian tạo có thể truy cập được trên nhiều hệ thống tệp hơn là chỉ các ext * ( debugfslà một công cụ cho các hệ thống tệp ext2 / 3/4 và không thể sử dụng trên các hệ thống khác). Nó đã làm việc cho một hệ thống XFS, nhưng không phải cho NTFS và exfat. Tôi đoán hệ thống tập tin FUSE cho những người không bao gồm thời gian tạo.


5

Có một trường hợp khác trong đó Thời gian sinh sẽ trống / không / dấu gạch ngang: Kích thước Inode của Ext4 phải có ít nhất 256byte để lưu trữ crtime. Sự cố xảy ra nếu ban đầu bạn tạo hệ thống tệp nhỏ hơn 512 MB (kích thước Inode mặc định sẽ là 128 byte, xem /etc/mke2fs.confmkfs.ext4manpage).

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

và / hoặc

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

Bây giờ hãy kiểm tra inode hệ thống tập tin (nó có đủ lớn để lưu trữ crtimekhông?):

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

Thông tin kỹ thuật: Trên trang Bố cục đĩa Ext4 , lưu ý rằng một số thuộc tính của bảng inode nằm ngoài 0x80 (128).


Đúng (Tôi nhớ đọc về điều này trên vger ). Giới hạn 512MB được xác định trong mke2fs.cdòng 1275
don_crissti

2

Đối với những gì đáng giá, tôi đã cảm thấy ấu dâm, vì vậy đã viết một bash Wrapper xung quanh stat để âm thầm hỗ trợ crtime bằng cách sử dụng debugfs để lấy nó từ một hệ thống tập tin ext4 bên dưới nếu có. Tôi hy vọng nó mạnh mẽ. Tìm nó ở đây .

Lưu ý rằng một bản sửa lỗi có vẻ bề ngoài trong danh sách việc cần làm cho Linux như được ghi lại trong tập lệnh đó. Vì vậy, trình bao bọc này có tuổi thọ danh nghĩa chỉ cho đến khi hoàn thành và là một bài tập trong những gì có thể làm được.


3
Lưu ý rằng xstat()cuối cùng đã được thêm vào Linux, vì vậy vấn đề chỉ còn là thời gian trước GNU libc và findthêm hỗ trợ cho nó.
Stéphane Chazelas

1
Tuyệt vời! Tin tốt thực sự.
Bernd Wechner

6
Với lời xin lỗi vì đã phạm tội, bạn dường như không hiểu ý nghĩa của "pedantic".
Nick

"Quá quan tâm đến chi tiết phút hoặc hình thức" - như trong, câu trả lời được chấp nhận là tốt, nhưng ... hãy chính thức hóa nó. ;-)
Bernd Wechner
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.