ファイルの 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
sync
debugfs からは依然として「最初の行」しか取得できません。行を追加したり、再度実行したり、数日後に再試行したりしても、この状況は変わりません。
debugfs がファイル内容の残りを表示しないのはなぜですか? debugfs の使い方が間違っているのでしょうか?
この動作は他のファイルでも確実に再現できます。
echo "New content" > data.txt
既存のファイルの内容を で上書きすると、debugfs は新しい内容を表示することに気付きました。ただし、2 行目を追加すると、上記のように、最初の行だけが表示されます。
私は Arch Linux 5.12.3 で debugfs 1.46.2 を使用しています。ファイルシステムは/dev/sda3
ext4 です。呼び出すと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 つのオプションがあります。
フラグを使用します
-D
:-D バッファをバイパスして、直接I/Oを使用してdebugfsがデバイスを開くようにします。 ferキャッシュ。Linuxデバイスの中には、特にデバイスマッパーが 現時点では、Direct I/O はサポートされていません。
バッファキャッシュを削除します:
エコー 1 | sudo tee /proc/sys/vm/drop_caches
例えば以下を参照してください:
- Linux システムでバッファとキャッシュを空にするにはどうすればよいでしょうか?
- https://www.kernel.org/doc/Documentation/sysctl/vm.txt
- /proc/sys/vm/ のドキュメントHTML (プレーンテキスト版の方が好きですが、まあ ;)
フラグを渡さない場合でも、結果をパイプすることで何らかのアクションを確認できます。-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/block
cat <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"