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).

두 번째 줄을 추가하면 문제가 발생합니다.

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가 새 내용을 표시한다는 것을 알았습니다 . 그러나 두 번째 줄을 추가하면 위에서 설명한 대로 첫 번째 줄만 표시됩니다.


저는 debugfs 1.46.2를 사용하여 Arch Linux 5.12.3을 사용하고 있습니다. 파일 시스템은 /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

캐싱 때문입니다. 최소한 두 가지 옵션이 있습니다.

  1. 플래그 를 사용하십시오 -D.

    -D debugfs가 버퍼를 우회하여 직접 I/O를 사용하여 장치를 열도록 합니다.
    캐시를 이용하세요. 일부 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 파일은 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/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"

관련 정보