Comment récupérer un fichier supprimé s'il est toujours ouvert par un processus?

19
$ cat important_file > /dev/null &
[1] 9711
$ rm important_file 
$ killall -STOP cat

[1]+  Stopped                 cat important_file > /tmp/p
$ ls -l /proc/`pidof cat`/fd/
total 0
lrwx------ 1 vi vi 64 May 13 20:32 0 -> /dev/pts/29
l-wx------ 1 vi vi 64 May 13 20:32 1 -> /tmp/p
lrwx------ 1 vi vi 64 May 13 20:32 2 -> /dev/pts/29
lr-x------ 1 vi vi 64 May 13 20:32 3 -> /home/vi/important_file (deleted)

Comment récupérer cela important_file?

J'ai essayé quelque chose comme

injcode -m dup2 -ofd=3 -ofilename=/tmp/recovered_file -oflags=O_CREAT $PID_OF_CAT

mais ça ne fait rien.

Vi.
la source

Réponses:

11

Si / home est NFS, il y aura un fichier .nfsNNNNNNNNNN dans / home / vi auquel vous pourrez accéder / copier. Si home est un système de fichiers local, vous devriez pouvoir faire la même chose via le lien / proc / PID / fd / 3:

cp /proc/PID/fd/3 /tmp/recovered_file

Si vous souhaitez réellement restaurer le fichier, voici un article de blog sur le sujet.

Mark Johnson
la source
1
OK, cela m'a dérouté readlink /proc/13381/fd/3-> "/ home / vi / important_file (supprimé)" et /home/vi/important_file\ \(deleted\)n'existe évidemment pas.
Vi.
22

... mieux que de copier à un moment donné (et de ne collecter que l'instantané du contenu du fichier) " tail -f" de copier ce fichier dans un nouveau fichier:

tail -c +0 -f /proc/PIDofProgram>/fd/# > /new/path/to/file

(grâce aux programmeurs prudents de tail, qui fonctionneront même avec la sortie binaire.)

Pendant son exécution, le tail -ffichier lui - même reste ouvert, l'empêchant en toute sécurité d'être purgé du disque à la fin du programme d'origine. Ainsi, ne vous arrêtez pas tail -fimmédiatement après la fin de votre programme original - vérifier la tail'ed d' /new/path/to/fileabord si c'est ce que vous voulez. Si ce n'est pas le cas (ou n'est pas satisfaisant pour toute autre raison), vous pouvez recopier le fichier d'origine, mais cette fois après tout, l'écriture est terminée par "Programme" et à partir de tail -f/ proc / PIDoftail / fd / répertoire.

Christian
la source
3
Qu'en est-il de la création d'un lien dur vers / proc / PIDofProgram> / fd / #?
Becko
2
@becko Invalid cross-device link.
Kamil Maciorowski
10

Utilisez lsof pour trouver le numéro d'inode et debugfs pour recréer un lien dur vers celui-ci. Par exemple:

# lsof -p 12345 | grep /var/log/messages
syslogd 12345 root    3w   REG                8,3    3000    987654 /var/log/messages (deleted)
# mount | grep var
/dev/sda2 on /var type ext3 (rw)
# debugfs -w /dev/sda2
debugfs: cd log
debugfs: ln <987654> tmp
debugfs: mi tmp
                      Mode    [0100600] 
                   User ID    [0] 
                  Group ID    [0] 
                      Size    [3181271] 
             Creation time    [1375916400] 
         Modification time    [1375916322] 
               Access time    [1375939901]
             Deletion time    [9601027] 0
                Link count    [0] 1
               Block count    [6232] 
                File flags    [0x0] 
...snip...
debugfs:  q
# mv /var/log/tmp /var/log/messages
# ls -al /var/log/messages
-rw------- 0 root root 3301 Aug  8 10:10 /var/log/messages

Avant de vous plaindre, j'ai truqué la transcription ci-dessus car je n'ai pas de fichier supprimé à portée de main en ce moment ;-)

J'utilise mipour réinitialiser le temps de suppression et le nombre de liens à des valeurs sensibles (0 et 1 respectivement), mais cela ne fonctionne pas correctement - vous pouvez voir que le nombre de liens reste à zéro ls. Je pense que le noyau pourrait mettre en cache les données d'inode. Vous devriez probablement fsck à la première occasion après avoir utilisé debugfs, pour être du bon côté.

D'après mon expérience, vous devez créer le lien en utilisant un nom de fichier temporaire, puis renommer le nom approprié. Le lier directement au nom de fichier d'origine semble entraîner une corruption de répertoire. YMMV!

Andrew Gallagher
la source
Pourquoi suggérez-vous exactement cela si cela ne fonctionne pas vraiment correctement et cause des dommages au système? Je pense que vous devriez avoir un avertissement plus vif dans la réponse que c'est simplement un WiP, et ne devrait pas vraiment être essayé en production.
2014
3

Vous pouvez simplement cple fichier, à savoir:

cp /proc/<pid>/fd/<fdno> /new/path/to/file

Bien sûr, si le fichier est toujours en cours de modification, vous rencontrerez des problèmes avec cette approche.

ninjalj
la source