debugfs catを使用して古いファイルデータを読み取る

debugfs catを使用して古いファイルデータを読み取る

inodeを使用してファイルの内容を読み取ろうとします。

これはうまくいきます:

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

debugfs はファイルの内容が「最初の行」であることを伝えます。コマンドのこの部分はdata.txtのinode番号を取得します$(stat -c %i data.txt)

2行目を追加すると問題が発生します。

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

私はまだdebugfsから「最初の行」だけを取得します。行を追加したり、やり直したり、数日後にやり直しても、syncこれは変わりません。

debugfsがファイルの残りの部分を表示しないのはなぜですか?私はdebugfsを間違った方法で使用していますか?

他のファイルを使用すると、この動作を確実に再現できます。


echo "New content" > data.txt既存のファイルコンテンツの上書きを使用すると、debugfsが新しいコンテンツを表示することがわかりました。ただし、上記のように2行目を追加すると、1行目のみが表示されます。


私はArch Linux 5.12.3でdebugfs 1.46.2を使用しています。ファイルシステムは/dev/sda3ext4です。呼び出しのdebugfs -R "stat ..."結果は次のとおりです。疑わしくない結果です。

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

ベストアンサー1

これはキャッシュのためです。少なくとも2つのオプションがあります。

  1. -Dフラグの使用:

    -Dはdebugfsが直接I / Oを使用してbufをバイパスしてデバイスを開くようにします。
    キャッシュを転送します。一部のLinuxデバイス、特に現在のデバイスマッパー
    この記事を書いている時点では、Direct I / Oはサポートされていません。
    

  2. バッファキャッシュを削除します。

    エコ1 | sudoティー/proc/sys/vm/drop_caches
    

例をご覧ください。


そのフラグを渡さない場合は、-D結果を次のようにパイプして一部の操作を表示できますxxd

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

あなたは見るでしょうcat'edファイルはゼロバイトで埋められ、時にはデータ(十分なデータが記録されている場合)で埋められます。

たとえば、echo A >data.txt

00000000: 410a                A.

それからfor i in {1..7}; do echo A >>data.txt; done

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

次の方法を使用して監視することもできます。

使用法:sudo ./script file_to_monitor

ファイル結果とともにデバイスの統計情報を印刷するwatchスクリプトから始まります。awk/sys/blockcat <inode>

#!/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"

おすすめ記事