Повторная ссылка на удаленный файл

33

Иногда люди удаляют файлы, которые они не должны, длительный процесс все еще имеет открытый файл, и восстановление данных с помощью catting /proc/<pid>/fd/Nпросто не достаточно круто . Достаточно удивительным было бы, если бы вы могли «отменить» удаление, запустив некоторую магическую опцию для ln, которая позволила бы вам повторно связать номер инода (восстановленный через lsof).

Я не могу найти никаких инструментов для Linux, чтобы сделать это, хотя бы с беглым гуглом.

Что у тебя, serverfault?

РЕДАКТИРОВАТЬ1: Причина, по которой файл загружается /proc/<pid>/fd/Nне достаточно круто , заключается в том, что процесс, в котором все еще открыт файл, все еще записывает в него файл. Удаление удаляет ссылку на индекс из пространства имен файловой системы. То, что я хочу, это способ воссоздания ссылки.

EDIT2: 'debugfs ln' работает, но риск слишком высок, так как он сбрасывает необработанные данные файловой системы. Восстановленный файл также безумно противоречив. Количество ссылок равно нулю, и я не могу добавить ссылки на него. Мне хуже от этого, так как я могу просто использовать /proc/<pid>/fd/Nдля доступа к данным, не портя мои фс.

mbac32768
источник

Ответы:

14

Достаточно удивительным было бы, если бы вы могли «отменить» удаление, запустив некоторую магическую опцию для ln, которая позволила бы вам повторно связать номер инода (восстановленный через lsof).

Эта удивительность была введена lnв v8.0 (GNU / coreutils) с -L|--logicalопцией, которая сначала вызывает lnразыменование /proc/<pid>/fd/<handle>. Так просто

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

достаточно, чтобы связать удаленный файл.

tnimeu
источник
7
Это не работает; если файл будет удален, произойдет сбой.
Random832
1
Нет не будет Я регулярно использую это для восстановления удаленных, но все еще открытых файлов. Но вы должны убедиться, что новый /path/to/deleted/fileнаходится в той же файловой системе, что и файл, который был до того, как он был удален, иначе это будет - действительно - не удастся. (Вы можете получить старый путь с помощью ls -l /proc/<pid>/fd/<handle>)
tnimeu
2
Такого рода функциональность (см. Этот вопрос и ответ) была специально отвергнута как угроза безопасности [гипотетической схеме безопасности, вращающейся вокруг привилегированного процесса, предоставляющей вашему процессу дескриптор файла только для чтения для файла, которым вы владеете, но в противном случае не имеете доступа к нему. ]; Я попробовал это (хотя с маленькой программой C, чтобы непосредственно использовать соответствующий системный вызов), и это не работало.
Random832
7
Я, конечно, проверил это перед публикацией своего решения, и в то время оно действительно работало для меня. То, о чем я не знал, это то, что он работал только на tmpfsфайловых системах, но не на, например ext3. Кроме того , эта функция получила полностью отключена в 2.6.39, см коммита . Поэтому, поэтому это решение больше не будет работать с ядром 2.6.39 или новее, а в более ранних версиях оно зависит от файловой системы.
tnimeu
7
@tnimeu ln -Lне работает для меня. У меня есть удаленный файл, и я попытался связать его с исходным путем. lnдает мне ln: failed to create hard link /my/path/file.pdf => /proc/19674/fd/16: No such file or directory. Но я могу, например, успешноcat /proc/19674/fd/16
Евгений Бересовский
13

Похоже, вы уже многое поняли, поэтому я не буду вдаваться в подробности. Есть несколько способов найти индекс, и вы обычно можете перехватить и перенаправить STDOUT. Вы можете использовать debugfs. Запустите эту команду в:

ln <$INODE> FILENAME

Убедитесь, что у вас есть резервные копии файловой системы. Возможно, вам понадобится запустить fsck позже. Я успешно проверил это с inode, все еще пишущим, и он действительно работает, чтобы создать новую жесткую ссылку на inode с разыменованными ссылками.

Если файл не связан с неоткрытым файлом в ext3, данные будут потеряны. Я не уверен, насколько это верно, но большая часть моего опыта восстановления данных связана с ext2. Из ext3 FAQ:

Q: Как я могу восстановить (восстановить) удаленные файлы из моего раздела ext3? На самом деле, вы не можете! Вот что сказал по этому поводу один из разработчиков, Андреас Дилгер:

Чтобы гарантировать, что ext3 сможет безопасно возобновить удаление связи после сбоя, он фактически обнуляет указатели блоков в inode, тогда как ext2 просто помечает эти блоки как неиспользуемые в растровых изображениях блоков и помечает inode как «удаленные» и покидает блок одни указатели.

Ваша единственная надежда - это "grep" для частей ваших файлов, которые были удалены, и надежда на лучшее.

В этом вопросе также есть соответствующая информация:

Я переписал большой файл с пустым на сервере Linux. Могу ли я восстановить существующий файл?

сигнализатор
источник
Комментарий, надеюсь, удален, так как не был откровенен.
MDPC
1
В случае удаленного, но все еще открытого файла, я не думаю, что он обнулит указатели в inode. Кроме того, вместо использования «ln» в debugfs я бы использовал «undel», чтобы счетчики ссылок на inode корректно обновлялись.
Марк Вагнер
Я не хотел ссылаться на это как таковое, эмбобо. Это не так, я проверил производительность. Я уточнил свой язык.
Уорнер
Умно, но портит мою файловую систему. :)
mbac32768
Это единственное решение для сценария, как вы его описали. Манипулирование файловой системой на низком уровне, на котором смонтирована rw и которая активно записывается, может привести к повреждению почти во всех сценариях.
Уорнер
8

способ отладки, как вы видели, на самом деле не работает, и в лучшем случае ваш файл будет удален автоматически (из-за журнала) после перезагрузки, и в худшем случае вы можете очистить файловую систему, что приведет к «циклу перезагрузки смерти». Правильное решение (TM) - выполнить восстановление на уровне VFS (что также дает дополнительное преимущество работы практически со всеми современными файловыми системами Linux). Путь системного вызова (flink) сбрасывается каждый раз, когда он появляется в LKML, поэтому лучше всего использовать модуль + ioctl.

Проект, который реализует этот подход и имеет достаточно маленький и чистый код, называется fdlink ( https://github.com/pkt/fdlink.git для версии, протестированной с ядром ubuntu maverick). С его помощью после того, как вы вставите модуль (sudo insmod flink_dev.ko), вы можете просто сделать «./flinkapp / proc // fd / X / my / link / path», и он будет делать именно то, что вы хотите.

Вы также можете использовать версию vfs-undelete.sourceforge.net с прямым переносом, которая также работает (и может также автоматически ссылаться на исходное имя), но код fdlink проще и работает так же хорошо, так что это мое предпочтение.

pktoss
источник
3

Я не знаю, как делать то, что вы хотите, но я бы сделал следующее:

  • Откройте файл RO из другого процесса
  • Подождите, пока оригинальный процесс для выхода
  • Скопируйте данные из вашего открытого FD в файл

Не идеально, конечно, но возможно. Другой вариант - поиграть с debugfs (используя linkкоманду), но это довольно страшно на рабочей машине!

Билл Вайс
источник
Команда debugfs link вообще не поддерживает этот вариант использования.
mbac32768
tldp.org/HOWTO/Ext2fs-Undeletion-11.html предполагает, что это так. Я не пробовал, но это кажется разумным.
Билл Вайс
linkне работал в моем тестировании, но lnсделал.
Уорнер
3

Столкнулся с той же проблемой сегодня. Лучшее, что я мог придумать, - это бежать

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

в сеансе tmux / screen до завершения процесса.

nickray
источник
2
Ссылка на оригинальные файлы, как и в принятом ответе, должна работать.
Крис С
1
Там нет принятого ответа на этот вопрос, какой из них вы имеете в виду?
Хамман Самуил
Разве для этого не нужно перенаправление ( >) на удаленный файл?
января
1

Интересный вопрос. Интервьюер задал мне тот же вопрос на собеседовании. То, что я сказал ему, было то, что не было легкого способа сделать это и вообще не стоило затраченного времени и усилий. Я спросил его, что он думает, что решение этой проблемы было ....

  1. Используйте lsof, чтобы найти номер инода на диске для процесса, так как он все равно будет отображаться, даже если файл был удален ... ключ в том, что он все еще открыт.
  2. Извлеките информацию из файловой системы на основе этого через отладчик файловой системы.
Якорь,
источник
Я могу просто извлечь данные из / proc / <pid> / fd / N, но это не то, что я пытаюсь сделать.
mbac32768
1

Используйте Sleuthkit icat.

sudo icat /dev/rdisk1s2 5484287 > accidentally_deleted_open_file
Исаак
источник
Это работает путем обхода функциональности файловой системы операционной системы и непосредственного разбора байтов диска.
Flimm
0

Быстрое решение, которое сработало для меня, без устрашающих инструментов:

1) найдите процесс + fd, посмотрев прямо в / proc:

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

2) Затем метод, аналогичный @ nickray, с pvдобавлением:

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

Вам может понадобиться Ctrl-C, когда вы закончите ( ls /proc/{procnum}/fd/{fdnum}скажет, что файл больше не существует)), но если вы знаете точный размер в байтах, вы можете использовать pv -Sего, чтобы завершить работу при достижении счетчика.

xenoid
источник