Geburt ist leer auf ext4


83

Ich habe gerade den BirthAbschnitt von gelesen statund es sieht so aus, als ob ext4 ihn unterstützen sollte, aber selbst eine Datei, die ich gerade erstellt habe, lässt ihn leer.

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

Warum füllt meine ext4Partition dieses Feld nicht aus?

Antworten:


93

Das Feld wird nur ausgefüllt (siehe unten) und coreutils statnicht angezeigt. Anscheinend warten sie 1 auf die xstat()Schnittstelle .

coreutils patches - aug. 2012 - HEUTE

stat (1) und ls (1) unterstützen die Geburtszeit. Abhängig davon, dass xstat () vom Kernel bereitgestellt wird

Sie erhalten die Erstellungszeit über debugfs:

debugfs -R 'stat <inode_number>' DEVICE

zB für mein /etc/profilewas ist an /dev/sda2(siehe So finden Sie heraus, auf welchem ​​Gerät sich eine Datei befindet ):

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 'Antwort auf LKML- Thread


7
@Sparhawk: Ich hatte dieses Problem auch mit einer Datei, /home/user/path/to/fileda /homesich diese auf einer separaten Partition befand. In diesem Fall muss der angegebene Pfad statrelativ zu sein /home. Beispiel: sudo debugfs -R 'stat user/path/to/file' /dev/sda2. Um die statsudo debugfs -R "stat <$(stat -c %i /home/user/path/to/file)>" /dev/sda5
Pfadbehandlung zu umgehen

3
Kann dies verwendet werden, um die Erstellungszeit von Dateien aus einem im Netzwerk eingebundenen Dateisystem abzurufen?
Taranaki

1
Dies ist also kein Zeitstempel, der über die Erstellung des Dateisystems hinausgeht. Wenn eine Datei vor 25 Jahren erstellt und über viele verschiedene physische oder gemountete Systeme kopiert wurde, gibt es überhaupt keine Möglichkeit, die Informationen zum Erstellungsdatum in den Metadaten zu finden? Die einzige Möglichkeit, um zu wissen, wann eine Datei erstellt wurde, besteht darin, sie in den Dateinamen einzugeben. Oder innerhalb des Inhalts? Gibt es einen Grund für diese anscheinend merkwürdige Nichtimplementierung?
Sinekonata

2
@sinekonata-Dateimetadaten sind sehr systemabhängig (wie diese Antwort zeigt, muss jede Ebene des Betriebssystems in der Lage sein, sie zu verarbeiten), und die kopienübergreifende Speicherung zwischen den Computern basiert auf der Unterstützung dieses Metadatenformats durch beide Systeme und das Kopiertool. Das bedeutet: Sie haben Glück, wenn Sie den Dateinamen nicht entstellt bekommen. Alternativ können Sie in einigen Dateiformaten Metadaten in die Datei einfügen (z. B. ID3 ), was im Allgemeinen gut funktioniert, aber in vielen Formaten ist eine solche Funktion nicht verfügbar. Schließlich können Sie die Datei in eine Archivdatei wie
André Paramés

1
Beachten Sie, dass die <und >um die Inode-Nummer erforderlich sind. Sie werden häufig in Beispielen verwendet, um eine Variable zu umgeben, die angepasst werden soll. In diesem Fall müssen sie jedoch wörtlich eingegeben werden. Ohne sie wird die Inode-Nummer als Pfad behandelt, und Sie erhalten eine File not found by ext2_lookupFehlermeldung.
15.

31

Ich habe dies zu einer einfachen Shell-Funktion kombiniert:

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
    }

Sie können es dann mit ausführen

$ 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

Die xstatFunktion wurde nie mit der Hauptlinie zusammengeführt. Ein neuer statxAufruf wurde jedoch später vorgeschlagen und in Linux 4.11 zusammengeführt . Der neue statx(2)Systemaufruf enthält eine Erstellungszeit in seiner Rückgabestruktur. Ein Wrapper für statx(2)wurde erst in 2.28 (Release August 2018) zu glibc hinzugefügt . Unterstützung für die Verwendung dieses Wrappers wurde in GNU Coreutils 8.31 (veröffentlicht im März 2019) hinzugefügt :

stat gibt jetzt die Erstellungszeit von Dateien aus, wenn dies vom Dateisystem unterstützt wird, auf GNU Linux-Systemen mit glibc> = 2.28 und 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

Was folgt, ist eine Demo, statxwo Userland noch aufholen muss (ältere glibc oder coreutils). Es ist nicht einfach, Systemaufrufe direkt in einem C-Programm aufzurufen. Normalerweise stellt glibc einen Wrapper zur Verfügung, der die Arbeit erleichtert, aber zum Glück hat @whotwagner ein Beispiel-C-Programm geschrieben , das zeigt, wie der statx(2)Systemaufruf auf x86- und x86-64-Systemen verwendet wird. Die Ausgabe hat dasselbe Format wie statdie Standardausgabe, jedoch ohne Formatierungsoptionen. Es ist jedoch einfach, das Format so zu ändern, dass nur die Geburtszeit gedruckt wird. (Wenn Sie einen neuen Glibc haben, brauchen Sie diesen nicht - Sie können ihn statxdirekt wie in beschrieben verwenden. man 2 statx)

Zuerst klonen Sie es:

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

Sie können den statx.cCode kompilieren oder, wenn Sie nur die Geburtszeit möchten, birth.cim geklonten Verzeichnis einen mit folgendem Code erstellen (dies ist eine minimale Version des statx.cAusdrucks nur des Erstellungszeitstempels einschließlich der Genauigkeit von Nanosekunden):

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

Dann:

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

Theoretisch sollte dies die Erstellungszeit auf mehr Dateisystemen als nur den ext * -Dateisystemen zugänglich machen ( debugfsist ein Werkzeug für ext2 / 3/4-Dateisysteme und auf anderen unbrauchbar). Es hat für ein XFS-System funktioniert, aber nicht für NTFS und exfat. Ich denke, die FUSE-Dateisysteme für diese enthielten nicht die Erstellungszeit.


5

In einem anderen Fall ist die Geburtszeit leer / Null / Bindestrich: Die Inode-Größe von Ext4 muss mindestens 256 Byte betragen, um gespeichert zu werden crtime. Das Problem tritt auf, wenn Sie ursprünglich erstellt das Dateisystem kleiner als 512 MB (Standardeinstellung Inode Größe werden 128 Bytes sein, sehen /etc/mke2fs.confund mkfs.ext4manpage).

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

und / oder

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

Überprüfen Sie nun den Dateisystem-Inode (ist er groß genug, um ihn zu speichern crtime?):

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

Technische Informationen: Beachten Sie auf der Seite Ext4-Festplattenlayout , dass einige Attribute der Inode-Tabellen größer als 0x80 (128) sind.


Richtig (ich erinnere mich, dass ich darüber auf vger gelesen habe ). Das 512-MB-Limit ist in mke2fs.cZeile 1275
don_crissti,

2

Für das, was es wert ist, fühlte ich mich pedantisch, also schrieb ich einen Bash-Wrapper um stat, um Crtime stillschweigend zu unterstützen, indem ich Debugfs verwendete, um es von einem zugrunde liegenden ext4-Dateisystem abzurufen, falls verfügbar. Ich hoffe es ist robust. Hier finden Sie es .

Beachten Sie, dass ein Fix angeblich in der Aufgabenliste für Linux enthalten ist, wie in diesem Skript dokumentiert. Dieser Wrapper hat also nur eine nominelle Lebensdauer, bis dies erledigt ist, und ist eher eine Übung in dem, was machbar ist.


3
Beachten Sie, dass xstat()Linux irgendwann hinzugefügt wurde, so dass es nur eine Frage der Zeit ist, bis die GNU libc und deren findUnterstützung hinzugefügt werden.
Stéphane Chazelas

1
Genial! Gute Nachrichten in der Tat.
Bernd Wechner

6
Wenn Sie sich dafür entschuldigen, pedantisch zu sein, scheinen Sie die Bedeutung von "pedantisch" nicht zu verstehen.
Nick

"Übermäßig besorgt um winzige Details oder Formalismen" - wie in, die akzeptierte Antwort ist in Ordnung, aber ... lassen Sie es uns formalisieren. ;-)
Bernd Wechner
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.