Relinking un file supprimé

Parfois, les gens suppriment les files qu'ils ne devraient pas, un process de longue durée a encore le file ouvert, et la récupération des données en utilisant /proc/<pid>/fd/N n'est tout simplement pas génial. Si vous pouviez "annuler" la suppression, exécutez une option magique, ce qui vous permettra de re-connecter au numéro d'inode (récupéré via lsof).

Je ne trouve aucun outil Linux pour le faire au less avec un Googling sommaire.

Qu'est-ce que vous avez, serverfault?

EDIT1: La raison pour laquelle le file du file /proc/<pid>/fd/N n'est pas génial, c'est parce que le process qui contient toujours le file est toujours écrit. Une suppression supprime la reference à l'inode à partir de l'espace de noms du système de files. Ce que je veux, c'est une façon de recréer la reference.

EDIT2: 'debugfs ln' fonctionne, mais le risque est trop élevé car il gèle datatables du système de files brut. Le file récupéré est également incohérent. Le nombre de liens est nul et je ne peux pas y append de liens. Je suis pire de cette façon car je peux simplement utiliser /proc/<pid>/fd/N pour accéder aux données sans corrompre mes fs.

Il semble que vous compreniez déjà beaucoup, alors je n'aurai pas trop de détails. Il existe plusieurs methods pour find l'inode et vous pouvez généralement cat et redirect STDOUT. Vous pouvez utiliser les debugfs . Exécutez cette command dans:

ln <$INODE> FILENAME

Assurez-vous d'avoir des sauvegardes du système de files. Vous devrez probablement exécuter une fsck par la suite. J'ai testé cela avec succès avec un inode encore écrit et fonctionne pour créer un nouveau lien dur vers un inode déféré.

Si le file est déconnecté avec un file non ouvert dans ext3, datatables sont perdues. Je ne sais pas à quel point c'est vrai, mais la plupart de mon expérience de récupération de données est avec ext2. À partir de l'ext3 FAQ:

Q: Comment puis-je récupérer (supprimer) les files supprimés de ma partition ext3? En fait, vous ne pouvez pas! C'est ce que l'un des développeurs, Andreas Dilger, a dit à ce propos:

Afin de s'assurer que ext3 peut reprendre en toute security un déconnection après une panne, il zéros réellement les pointeurs de bloc dans l'inode, alors que ext2 marque ces blocs comme inutilisés dans les bitmaps du bloc et marque l'inode comme "supprimé" et quitte le bloc des repères isolés.

Votre seul espoir est de «grep» pour certaines parties de vos files qui ont été supprimés et espérant le mieux.

Il y a également des informations pertinentes sur cette question:

J'ai écrasé un grand file avec un blanc sur un server linux. Puis-je récupérer le file existant?

Si vous pouviez "annuler" la suppression, exécutez une option magique, ce qui vous permettra de re-connecter au numéro d'inode (récupéré via lsof).

Cette nouveauté a été introduite dans ln in v8.0 (GNU / coreutils) avec l'option -L|--logical qui provoque la déreference d'un /proc/<pid>/fd/<handle> premier. Donc, un simple

 ln -L /proc/<pid>/fd/<handle> /path/to/deleted/file 

est suffisant pour relayer un file supprimé.

la manière de déboguer comme vous l'avez vu ne fonctionne pas vraiment et, au mieux, votre file sera automatiquement supprimé (en raison du journal) après le redémarrage et, au pire, vous pouvez supprimer votre système de files en «redémarrant le cycle de décès». La solution correcte (TM) consiste à effectuer la numération dans le niveau VFS (qui a également l'avantage supplémentaire de travailler avec pratiquement tous les filesystems Linux actuels). Le système d'appel (flink) a été abattu chaque fois qu'il apparaissait dans LKML, de sorte que le meilleur moyen est de passer par un module + ioctl.

Un projet qui implémente cette approche et a un code raisonnablement petit et propre est fdlink ( https://github.com/pkt/fdlink.git pour une version testée avec le kernel de Ubuntu Maverick). Avec, après avoir inséré le module (sudo insmod flink_dev.ko), vous pouvez simplement faire "./flinkapp / proc // fd / X / my / link / path" et il fera exactement ce que vous voulez.

Vous pouvez également utiliser une version à l'avant-plan de vfs-undelete.sourceforge.net qui fonctionne également (et peut également relayer automatiquement le nom d'origine), mais le code de fdlink est plus simple et fonctionne aussi bien, donc c'est ma preference.

Je ne sais pas comment faire exactement ce que vous voulez, mais ce que je ferais, c'est:

  • Ouvrir le file RO à partir d'un autre process
  • Attendez que la procédure initiale soit sortie
  • Copiez datatables de votre FD ouvert vers un file

Pas idéal, évidemment, mais possible. L'autre option est de jouer avec debugfs (à l'aide de la command de link ), mais c'est un peu effrayant sur une machine de production!

J'ai couvert le même problème aujourd'hui. Le meilleur que je pourrais proposer est de courir

 % tail -n +0 -f /proc/<pid>/fd/<fd> /path/to/deleted_file 

dans une session tux / écran jusqu'à ce que le process se termine.

Question intéressante. Un interviewer m'a posé la même question lors d'une entrevue de travail. Ce que je lui ai dit, c'est qu'il n'y avait pas un moyen simple de le faire et en général ne valait pas le time et les efforts. Je lui ai demandé ce qu'il pensait que la solution à cette question était …

  1. Utilisez lsof pour find le numéro d'inode sur le disque pour le process, car il apparaîtra même si le file a été supprimé … la key est qu'elle est toujours ouverte.
  2. Extrayez les informations du système de files en fonction de cela via un débogueur de système de files.

Utilisez Sleuthkit icat.

 sudo icat /dev/rdisk1s2 5484287 > accidentally_deleted_open_file 

La solution rapide qui a fonctionné pour moi, sans outils intimidants:

1) find le process + fd en regardant directement dans / proc:

 ls -al /proc/*/fd/* 2>/dev/null | grep {filename} 

2) Ensuite, une technique similaire à @ nickray's, avec pv jeté dans:

 tail -c +0 -f /proc/{procnum}/fd/{fdnum} | pv -s {expectedsize} > {recovery_filename} 

Vous devrez peut-être Ctrl-C lorsque vous avez terminé ( ls /proc/{procnum}/fd/{fdnum} vous diront que le file n'existe plus), mais si vous connaissez la taille exacte des octets, vous pouvez utiliser pv -S pour le faire sortir lorsque le count est atteint.