Como recuperar o arquivo deletado se ainda estiver aberto por algum processo?

16
$ 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)

Como recuperar este important_file ?

Eu tentei algo como

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

mas não faz nada.

    
por Vi. 13.05.2011 / 19:43

4 respostas

9

Se / home for NFS, haverá um arquivo .nfsNNNNNNNNNN em / home / vi que você pode acessar / copiar. Se home for um sistema de arquivos local, você poderá fazer o mesmo através do link / proc / PID / fd / 3:

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

Se você deseja realmente recuperar o arquivo, aqui está uma postagem no blog sobre o assunto.

    
por 14.05.2011 / 01:38
16

... melhor que copiar em um determinado momento (e reunir apenas o instantâneo da hora do conteúdo do arquivo) é " tail -f " esse arquivo em um novo arquivo:

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

(graças aos programadores cautelosos de tail, que até trabalharão com saída binária).

Durante seu tempo de execução, o próprio tail -f mantém o arquivo aberto, evitando que ele seja removido do disco quando o programa original terminar. Assim, não pare o tail -f imediatamente após o seu programa original terminar - verifique se o /new/path/to/file é o primeiro, se é o que você quer. Se não é (ou é insatisfatório por qualquer outro motivo), você pode copiar o arquivo original novamente, mas desta vez após todo o texto foi finalizado por "Program" e do ainda em execução Diretório tail -f '/ proc / PIDoftail / fd /.

    
por 28.05.2013 / 12:18
8

Use lsof para encontrar o número do inode e debugfs para recriar um link físico para ele. Por exemplo:

# 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

Antes de você reclamar, eu formei a transcrição acima, pois não tenho um arquivo deletado para entregar agora; -)

Eu uso mi para redefinir o tempo de exclusão e a contagem de links para valores sensíveis (0 e 1, respectivamente), mas isso não funciona corretamente - você pode ver que a contagem de links permanece em zero em ls . Eu acho que o kernel pode estar armazenando em cache os dados do inode. Você provavelmente deve fazer o fsck na primeira oportunidade depois de usar o debugfs, para estar no lado seguro.

Na minha experiência, você deve criar o link usando um nome de arquivo temporário e, em seguida, renomear para o nome adequado. Vinculá-lo diretamente ao nome do arquivo original parece causar corrupção de diretório. YMMV!

por 08.08.2013 / 12:24
3

Você pode apenas cp do arquivo, por exemplo:

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

É claro que, se o arquivo ainda estiver sendo modificado, você terá problemas com essa abordagem.

    
por 14.05.2011 / 01:55