Как восстановить удаленный файл, если он все еще открыт каким-либо процессом?

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

как восстановить этот important_file?

Я пробовал что-то вроде

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

но он ничего не делает.

4 ответа:

Если /home NFS, будет .файл nfsNNNNNNNNNN в /home/vi, к которому можно получить доступ / скопировать. Если home является локальной файловой системой, вы должны быть в состоянии сделать то же самое через /proc/PID/fd/3 ссылка:

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

Если вы хотите на самом деле восстановить файл, вот блоге на эту тему.

... лучше, чем копирование в данный момент времени (и сбор только моментального снимка содержимого файла),"tail -f" файл в новый файл:

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

(благодаря осторожным программистам tail, которые будут работать даже с двоичным выходом.)

во время выполнения tail -f сам держит файл открытым, безопасно предотвращая его от очистки с диска, когда оригинальная программа заканчивается. Таким образом, не останавливайте tail -f сразу после окончания программы - проверить хвост объед ли и то, что вы хотите. Если это не так (или неудовлетворительно по любой другой причине), вы можете скопировать исходный файл еще раз, но на этот раз после все записи в него уже готовые "программы" и под управлением tail -f's /proc/PIDoftail/FD/ каталог.

используйте lsof, чтобы найти номер индекса, и debugfs, чтобы воссоздать жесткую ссылку на него. Например:

# 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

прежде чем жаловаться, я подделал выше стенограмму, как у меня нет удаленного файла, чтобы передать прямо сейчас ; -)

Я использую mi чтобы сбросить время удаления и количество ссылок до разумных значений (0 и 1 соответственно), но это не работает должным образом - вы можете видеть, что количество ссылок остается на нуле в ls. Я думаю, что ядро может кэшировать данные индекса. Вы вероятно, следует fsck при первой возможности после использования debugfs, чтобы быть в безопасности.

по моему опыту, вы должны создать ссылку, используя временное имя файла, а затем переименовать в собственное имя. Связывание его непосредственно с исходным именем файла, по-видимому, вызывает повреждение каталога. МММ!

можно просто cp файл, я.е:

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