Я пытаюсь прочитать содержимое файла, используя его inode.
Это работает отлично:
echo "First line" > data.txt
sync
sudo debugfs -R "cat <$(stat -c %i data.txt)>" /dev/sda3
debugfs сообщает мне, что содержимое файла — «Первая строка». Эта часть команды получает номер inode data.txt: $(stat -c %i data.txt)
.
При добавлении второй строки все идет наперекосяк:
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 показывает новое содержимое. Но добавление к нему второй строки, как описано выше, покажет только первую строку.
Я работаю на 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
Это из-за кэширования. У вас есть как минимум два варианта.
Используйте
-D
флаг:-D Заставляет debugfs открывать устройство с помощью прямого ввода-вывода, минуя буфер. fer кэш. Обратите внимание, что некоторые устройства Linux, в частности, устройство сопоставления, как в этом тексте не поддерживается прямой ввод-вывод.
Удалить кэш буфера:
echo 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
Файл заполняется нулевыми байтами, а иногда и данными (если записано достаточно).
Например, после того, как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"