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)
.
두 번째 줄을 추가할 때 문제가 발생합니다.
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가 직접 I/O를 사용하여 buf를 우회하여 장치를 열도록 합니다. 캐시를 전송합니다. 일부 Linux 장치, 특히 현재 장치 매퍼는 이 글을 쓰는 시점에서는 Direct I/O가 지원되지 않습니다.
버퍼 캐시를 삭제합니다.
에코 1 | sudo 티 /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 파일은 0바이트로 채워지고 때로는 데이터(충분한 데이터가 기록된 경우)로 채워집니다.
예를 들어, 이후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"