Lesen veralteter Dateidaten mit debugfs cat

Lesen veralteter Dateidaten mit debugfs cat

Ich versuche, den Inhalt einer Datei mithilfe des Inodes der Datei zu lesen.

Das funktioniert gut:

echo "First line" > data.txt
sync
sudo debugfs -R "cat <$(stat -c %i data.txt)>" /dev/sda3

debugfs sagt mir, dass der Dateiinhalt „Erste Zeile“ ist. Dieser Teil des Befehls ruft die Inode-Nummer von data.txt ab: $(stat -c %i data.txt).

Beim Hinzufügen einer zweiten Zeile kann es zu Problemen kommen:

echo "Second line" >> data.txt
sync
sudo debugfs -R "cat <$(stat -c %i data.txt)>" /dev/sda3

Ich bekomme immer noch nur „Erste Zeile“ von debugfs. Dies ändert sich nicht, wenn ich weitere Zeilen hinzufüge, es syncerneut ausführe oder es ein paar Tage später erneut versuche.

Warum zeigt debugfs nicht den Rest des Dateiinhalts an? Verwende ich debugfs falsch?

Ich kann dieses Verhalten mit anderen Dateien zuverlässig reproduzieren.


Mir ist aufgefallen, dass debugfs beim Überschreiben bestehender Dateiinhalte mit echo "New content" > data.txtden neuen Inhalt anzeigt. Wenn Sie jedoch eine zweite Zeile hinzufügen, wird, wie oben beschrieben, nur die erste Zeile angezeigt.


Ich verwende Arch Linux 5.12.3 mit debugfs 1.46.2. Das Dateisystem /dev/sda3ist ext4. Der Aufruf debugfs -R "stat ..."ergibt folgendes, was mir nicht verdächtig vorkommt:

Inode: 16515371   Type: regular    Mode:  0644   Flags: 0x80000
Generation: 3923658711    Version: 0x00000000:00000001
User:  1000   Group:  1000   Project:     0   Size: 34
File ACL: 0
Links: 1   Blockcount: 8
Fragment:  Address: 0    Number: 0    Size: 0
ctime: 0x60b639e5:71315fa0 -- Tue Jun  1 15:45:09 2021
atime: 0x60b63988:b7c456cc -- Tue Jun  1 15:43:36 2021
mtime: 0x60b639e5:71315fa0 -- Tue Jun  1 15:45:09 2021
crtime: 0x60b63988:b7c456cc -- Tue Jun  1 15:43:36 2021
Size of extra inode fields: 32
Inode checksum: 0xbfa4390e
EXTENTS:
(0):66095479

Antwort1

Es liegt am Caching. Sie haben mindestens zwei Möglichkeiten.

  1. Verwenden Sie die -DFlagge:

    -D Bewirkt, dass debugfs das Gerät mit Direct I/O öffnet und den Puffer umgeht.
    fer-Cache. Beachten Sie, dass einige Linux-Geräte, insbesondere Device-Mapper ab
    Zum Zeitpunkt des Schreibens wird Direct I/O nicht unterstützt.
    

  2. Puffercache löschen:

    echo 1 | sudo tee /proc/sys/vm/drop_caches
    

Siehe zum Beispiel:


Wenn Sie das Flag nicht übergeben, -Dkönnen Sie dennoch eine Aktion sehen, indem Sie das Ergebnis beispielsweise weiterleiten an xxd:

sudo debugfs -R "cat <$(stat --printf %i data.txt)>" /dev/sda3 | xxd -a -c 32

Sie werden sehen, dass diecatDie bearbeitete Datei wird mit Nullbytes und manchmal mit Daten gefüllt (wenn genug geschrieben wurden).

Zum Beispiel nachecho A >data.txt

00000000: 410a                A.

Dann danach for i in {1..7}; do echo A >>data.txt; done:

00000000: 410a 0000 0000 0000 0000 0000 0000 0000  A...............

Sie können die Überwachung auch mit folgendem Verfahren durchführen:

Verwendung:sudo ./script file_to_monitor

Es wird watchmit einem awkSkript gestartet, das Statistiken für das Gerät druckt und /sys/blockzusätzlich die Ergebnisse cat <inode>in eine Datei druckt.

#!/bin/sh

if [ "$1" = "-h" ]; then
    printf '%s FILE\n' "$0"
    exit 1
fi

file="$1"
inode=$(stat --printf %i "$file")
dev_path="$(df -P -- "$file" | awk 'END{print $1}')"
dev_name="$(lsblk -no NAME  "$dev_path")"
dev_core="$(lsblk -no PKNAME  "$dev_path")"

if [ "$dev_core" = "loop" ]; then
    fn_stat=/sys/block/$dev_name/stat
else
    fn_stat=/sys/block/$dev_core/$dev_name/stat
fi

printf 'File : %s\n' "$file"
printf 'Inode: %s\n' "$inode"
printf 'Stat : %s\n' "$fn_stat"
printf 'Dev  : %s\n' "$dev_path"

printf "Continue? [yN] " >&2
read -r ans
if ! [ "$ans" = "y" ] && ! [ "$ans" = "Y" ]; then
    exit
fi

watch -n 0.2 'awk \
    -v inode="'$inode'" \
    -v dev_path="'$dev_path'" \
"{
    rs = \$3 * 512
    rsk = rs / 1024
    rsm = rsk / 1024
    ws = \$7 * 512
    wsk = ws / 1024
    wsm = wsk / 1024

    printf \" 1: Reads  Completed   : %9d\n\", \$1
    printf \" 2: Reads  Merged      : %9d\n\", \$2
    printf \" 3: Read   Sectors     : %9d %6d MiB %9d KiB %d bytes\n\",
    \$3, rsm, rsk, rs
    printf \" 4: Read   ms          : %9d\n\", \$4
    printf \" 5: Writes Completed   : %9d\n\", \$5
    printf \" 6: Writes Merged      : %9d\n\", \$6
    printf \" 7: Write  Sectors     : %9d %6d MiB %9d KiB %d bytes\n\",
    \$7, wsm, wsk, rs
    printf \" 8: Write  ms          : %9d\n\", \$8
    printf \" 9: I/Os   in progress : %9d\n\", \$9
    printf \"10: I/O    ms          : %9d\n\", \$10
    printf \"11: I/O    ms weighted : %9d\n\", \$11

    printf \"\n\nFILE <%d> %s:\n\", inode, dev_path

    system(\"sudo debugfs -R '\''cat <\"inode\">'\'' \"dev_path\" | xxd -a -c 32\")
}
"' "$fn_stat"

verwandte Informationen