Lectura de datos de archivos obsoletos con debugfs cat

Lectura de datos de archivos obsoletos con debugfs cat

Estoy intentando leer el contenido de un archivo usando el inodo del archivo.

Esto funciona bien:

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

debugfs me dice que el contenido del archivo es "Primera línea". Esta parte del comando obtiene el número de inodo de data.txt: $(stat -c %i data.txt).

Las cosas salen mal al agregar una segunda línea:

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

Todavía solo obtengo la "Primera línea" de debugfs. Esto no cambia después de agregar más líneas, ejecutar syncnuevamente o volver a intentarlo un par de días después.

¿Por qué debugfs no muestra el resto del contenido del archivo? ¿Estoy usando debugfs de forma incorrecta?

Puedo reproducir este comportamiento de forma fiable con otros archivos.


Noté que al sobrescribir el contenido del archivo existente con echo "New content" > data.txt, debugfs muestra el nuevo contenido. Pero agregarle una segunda línea, como se describió anteriormente, mostrará solo la primera línea.


Estoy en Arch Linux 5.12.3 usando debugfs 1.46.2. El sistema de archivos /dev/sda3es ext4. Llamar debugfs -R "stat ..."produce lo siguiente, lo cual no me parece sospechoso:

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

Respuesta1

Se debe al almacenamiento en caché. Tienes al menos dos opciones.

  1. Usa la -Dbandera:

    -D Hace que debugfs abra el dispositivo mediante E/S directa, evitando el búfer.
    caché de transferencia. Tenga en cuenta que algunos dispositivos Linux, en particular el mapeador de dispositivos a partir de
    este escrito, no admiten E/S directa.
    

  2. Eliminar caché del búfer:

    eco 1 | sudo tee /proc/sys/vm/drop_caches
    

Ver por ejemplo:


Si no pasa la -Dbandera, aún puede ver alguna acción canalizando el resultado a, por ejemplo xxd:

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

Verás que elcatEl archivo editado se llena con cero bytes y, a veces, con datos (si se han escrito suficientes).

Por ejemplo, despuésecho A >data.txt

00000000: 410a                A.

A continuación, después for i in {1..7}; do echo A >>data.txt; done:

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

También puedes monitorear usando algo como esto:

Uso:sudo ./script file_to_monitor

Se inicia watchcon un awkscript que imprime estadísticas para el dispositivo /sys/blockademás de imprimir el resultado cat <inode>del archivo.

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

información relacionada