Estou tentando ler o conteúdo de um arquivo usando o inode do arquivo.
Isso funciona bem:
echo "First line" > data.txt
sync
sudo debugfs -R "cat <$(stat -c %i data.txt)>" /dev/sda3
debugfs me diz que o conteúdo do arquivo é "Primeira linha". Esta parte do comando obtém o número do inode do data.txt: $(stat -c %i data.txt)
.
As coisas dão errado ao adicionar uma segunda linha:
echo "Second line" >> data.txt
sync
sudo debugfs -R "cat <$(stat -c %i data.txt)>" /dev/sda3
Ainda recebo apenas "Primeira linha" do debugfs. Isso não muda depois de adicionar mais linhas, executar sync
novamente ou tentar novamente alguns dias depois.
Por que o debugfs não mostra o restante do conteúdo do arquivo? Estou usando debugfs da maneira errada?
Posso reproduzir esse comportamento de forma confiável com outros arquivos.
Percebi que ao substituir o conteúdo do arquivo existente echo "New content" > data.txt
, o debugfs mostra o novo conteúdo. Mas adicionar uma segunda linha a ele, conforme descrito acima, mostrará apenas a primeira linha.
Estou no Arch Linux 5.12.3 usando debugfs 1.46.2. O sistema de arquivos ativado /dev/sda3
é ext4. Chamar debugfs -R "stat ..."
produz o seguinte, o que me parece insuspeito:
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
Responder1
É devido ao cache. Você tem pelo menos duas opções.
Use a
-D
bandeira:-D Faz com que o debugfs abra o dispositivo usando Direct I/O, ignorando o buf- para cache. Observe que alguns dispositivos Linux, principalmente o mapeador de dispositivos a partir de deste documento, não suportam Direct I/O.
Eliminar cache do buffer:
eco 1 | sudo tee /proc/sys/vm/drop_caches
Veja por exemplo:
- Como você esvazia os buffers e o cache em um sistema Linux?
- https://www.kernel.org/doc/Documentation/sysctl/vm.txt
- Documentação para /proc/sys/vm/HTML (eu gosto mais da variante de texto simples, mas ei;)
Se você não passar o -D
sinalizador, ainda poderá ver alguma ação canalizando o resultado para, por exemplo xxd
:
sudo debugfs -R "cat <$(stat --printf %i data.txt)>" /dev/sda3 | xxd -a -c 32
Você verá que ocat
O arquivo 'ed é preenchido com zero bytes e, às vezes, com dados (se o suficiente tiver sido gravado).
Por exemplo, depoisecho A >data.txt
00000000: 410a A.
Então depois for i in {1..7}; do echo A >>data.txt; done
:
00000000: 410a 0000 0000 0000 0000 0000 0000 0000 A...............
Você também pode monitorar usando algo assim:
Uso:sudo ./script file_to_monitor
Ele é iniciado watch
com um awk
script que imprime estatísticas do dispositivo e /sys/block
também imprime o resultado cat <inode>
do arquivo.
#!/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"