Batch processando um mapfile ddrescue com debugfs

1

Eu tenho um mapfile produzido por ddrescue , que lista 418 setores defeituosos, onde cada linha se parece com isso (o sinal de menos indica um bloco defeituoso):

Position      Size
0x1CC7C68000  0x00001000  -

Ao converter a posição em bytes para o número de setor relativo da partição, posso usar debugfs para consultar o número do inode e, em seguida, localizar o caminho do arquivo quebrado. Fazer isso manualmente não é viável para quase 2000 blocos defeituosos, então eu gostaria de automatizar isso, existe uma maneira de fazer o script debugfs executar uma seqüência de comandos em um sistema de arquivos?

Aqui está o que estou fazendo atualmente para obter o nome do arquivo de um setor quebrado:

  1. As posições no ddrescue mapfile estão em bytes em relação ao início do disco. Primeiro, eu converto a posição para o número do setor dividindo com 512 e então subtraio a posição start sektor da partição:

    Partição do primeiro setor: 91914240 Posição do bloco ruim: 0x1CC7C68000    Em casas decimais: 123610759168    Posição setorial absoluta: 123610759168/512 = 241427264    Posição relativa do bloco na partição: 241427264 - 91914240 = 149513024

Portanto, o setor defeituoso está em 149513024 em relação ao início da partição, usando debugfs Agora posso encontrar o inode:

$ debugfs
debugfs: open /dev/sdd3
debugfs: icheck 149513024
Block       Inode number
149513024   1183169
debugfs: ncheck 1183169
Inode   Pathname
1183169 /username/foo/bar/baz

Eu gostaria de automatizar esse processo para que eu possa passar uma lista de posições de bloco para debugfs , resolver esses blocos em inodes, filtrar os inodes para excluir inodes não mapeados e usar ncheck para resolver os nomes de caminho para o restantes inodes. Isso é possível com debugfs e alguns scripts de shell?

    
por lanoxx 05.10.2018 / 15:05

1 resposta

0

Eu acredito que encontrei uma solução para o meu problema. No entanto, ainda estou curioso para saber se alguém pode encontrar uma solução mais elegante ou possivelmente encontrar um erro na minha solução.

Como se constata, eu poderia escrever para stdin de debugfs , então eu só precisei gerar uma seqüência de comandos para debugfs , para analisar a saída de ddrescue .

O seguinte script bash assume que um arquivo chamado mapfile.ddrescue está presente no diretório atual que foi produzido por ddrescue .

for line in \
    $(cat mapfile.ddrescue | \
      grep -e "-$" | \
      awk -F" " '{print $1}' | \
      awk -F"0x" '{print $2}'); \
do \
    position=$(( 16#$line / 512 - 91914240 )); \
    result="$result $position"; \
done; \
echo -e "open /dev/sdd3\nicheck $result\nquit\n" | sudo debugfs

Veja o que este script faz:

  1. Eu analiso o mapfile de ddrescue , que eu nomeei de mapfile.ddrescue .
  2. Filtrei para manter apenas as linhas que terminam com um hífen. Essas são as posições com maus blocos.
  3. Eu uso o awk para dividir no espaço em branco e imprimir o primeiro token que é a posição. Isto irá conter um número hexadecimal como 0x34A933F000.
  4. eu removo o prefixo Ox .
  5. O resultado é retornado pela mão de chamada $(...) que serve como entrada para o loop for, portanto, a linha sempre conterá uma posição.
  6. Eu uso a expressão $(( ... )) para calcular matemática na posição, dividir a posição por 512 (por exemplo, bytes por setor) e subtrair o início da partição que no meu caso é 91914240 . Isto dá uma posição em sektors em relação ao início da partição.
  7. Eu concateno cada posição em uma lista separada por espaços que é armazenada em $result .
  8. Finalmente, eu gero uma lista de comandos separada por nova linha, a qual canaliza para stdin do comando debugfs que eu executo com sudo. O comando abre o dispositivo (no meu caso /dev/sdd3 ). Em seguida, ele executa icheck no $result e sai de debugfs .

Quando eu executei este script, debugfs demorou muito tempo para encontrar todos os inodes para esses blocos, no meu caso, ele ficou pendurado por vários minutos até que imprimisse a saída.

Quando o script foi concluído, copiei o resultado em um arquivo de texto e o analisei. Felizmente, a maioria dos setores apontava para blocos não alocados e os demais apontavam para os mesmos números inode . Depois de remover linhas com <block not found> e remover duplicatas, apenas quatro inodes permaneciam, o que eu podia verificar manualmente com debugfs usando ncheck . Isso me deu quatro caminhos de arquivo, esses são os arquivos que eu agora tentarei restaurar de um backup.

Plano de fundo Eu originalmente comecei com dd e queria copiar o conteúdo de um SSD de 256GB para um SSD maior. dd foi anulado com erros de E / S em aproximadamente 45/185 GB da última partição. No entanto, com ddrescue , economize 99,99% da unidade. Finalmente, com a solução acima, eu fui capaz de verificar em quais arquivos 1700kb ou 418 áreas ruins pertencem e encontrei apenas quatro arquivos que estão quebrados. Isso aumentou bastante minha confiança nos dados restaurados, pois agora sei quais arquivos estão corrompidos e posso restaurá-los de um backup mais antigo.

    
por 05.10.2018 / 20:38