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 sync
nuevamente 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/sda3
es 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.
Usa la
-D
bandera:-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.
Eliminar caché del búfer:
eco 1 | sudo tee /proc/sys/vm/drop_caches
Ver por ejemplo:
- ¿Cómo se vacían los buffers y el caché en un sistema Linux?
- https://www.kernel.org/doc/Documentation/sysctl/vm.txt
- Documentación para /proc/sys/vm/HTML (me gusta más la variante de texto plano, pero bueno;)
Si no pasa la -D
bandera, 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 elcat
El 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 watch
con un awk
script que imprime estadísticas para el dispositivo /sys/block
ademá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"