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 sync
erneut 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.txt
den 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/sda3
ist 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.
Verwenden Sie die
-D
Flagge:-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.
Puffercache löschen:
echo 1 | sudo tee /proc/sys/vm/drop_caches
Siehe zum Beispiel:
- Wie leeren Sie die Puffer und den Cache auf einem Linux-System?
- https://www.kernel.org/doc/Documentation/sysctl/vm.txt
- Dokumentation für /proc/sys/vm/HTML (mir gefällt die reine Textvariante besser, aber hey ;)
Wenn Sie das Flag nicht übergeben, -D
kö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 diecat
Die 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 watch
mit einem awk
Skript gestartet, das Statistiken für das Gerät druckt und /sys/block
zusä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"