Niveau :
Résumé : lsof | grep delete ; cat /proc/$PID/fd/$FD
Suite à un article récent, vous avez constaté que certains de vos processus utilisent des fichiers qui ont été supprimés. Que se passe-t-il si vous voulez les récupérer ? (un logrotate apache qui s'est mal passé par exemple).
Pour cela, il suffit de regarder votre ligne lsof
$ lsof | grep delete
Regardez les valeurs qui en sortent :
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
Je vous conseille le man de lsof à la section OUTPUT pour les champs que vous ne comprenez pas.
Notez que FD ne contient pas toujours le file descriptor, mais parfois la méthode d'ouverture du fichier. En effet, un certain nombre de fichier n'est pas ouvert avec la commande open (exemple mmap ou le binaire lui-même). Ce qui nous intéresse est donc un nombre suivi de r, w ou u.
Remarquez que nous avons l'inode du fichier ce qui nous permettra d'imaginer une autre technique de récupération.
Maintenant récupérons :
$ cp /proc/$PID/fd/$FD /tmp/sauvegarde
Et voilà
La même chose en plus dur
Donc, je disais une autre méthode (pour laquelle il faut être root et avoir un système de fichier ext2/ext3). On va d'abord s'assurer que la technique fonctionne en lisant le contenu du fichier :
# remplacez par le /dev/kivabien (déduit de $DEVICE) $ echo "cat <$INODE>" | debugfs /dev/sda3
Cool ça marche, maintenant nous allons pouvoir recréer l'entrée du fichier inline (pratique pour les gros fichiers quand on n'a plus de place). Attention, méthode barbare :
# pour forcer le noyau a relire les entrées après $ sync # on recrée l'entrée sans passer par le noyal # attention, $NAME est relatif à la partition $ echo "ln <$NODE> $NAME" | debugfs -w /dev/sda3
Et voila pas besoin de recopier le fichier. Par contre on a fait ça sans passer par le système, ce qui veut dire que :
- le noyau voit toujours le fichier dans lsof | grep delete
- le répertoire parent ne doit pas être utilisé entre le sync et le debugfs (en particulier, vous ne devez pas être dedans) sinon le noyau ne va rien comprendre et votre fichier ne sera pas restauré correctement)
C'est une méthode barbare, mais il existe aussi une méthode propre offline (qui marche, euh ... souvent) :
$ umount /dev/sda3 $ echo "ln <$NODE> $NAME" | debugfs -w /dev/sda3 $ mount /dev/sda3
Comments