Назад | Перейти на главную страницу

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

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

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

Что у вас, serverfault?

EDIT1: причина загрузки файла из /proc/<pid>/fd/N недостаточно круто, потому что процесс, у которого все еще открыт файл, все еще пишет в него. Удаление удаляет ссылку на индексный дескриптор из пространства имен файловой системы. Я хочу способ воссоздать ссылку.

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

Было бы неплохо, если бы вы могли «отменить» удаление, запустив некую волшебную опцию для ln, которая позволила бы вам повторно привязать к номеру inode (восстановлен с помощью lsof).

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

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

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

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

ln <$INODE> FILENAME

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

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

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

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

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

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

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

способ debugfs, как вы видели, на самом деле не работает, и в лучшем случае ваш файл будет автоматически удален (из-за журнала) после перезагрузки, а в худшем случае вы можете уничтожить свою файловую систему, что приведет к «циклу смерти перезагрузки». Правильное решение (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 проще и работает так же хорошо, поэтому я предпочитаю это.

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

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

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

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

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

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

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

  1. Используйте lsof, чтобы найти номер inode на диске для процесса, поскольку он все равно будет отображаться, даже если файл был удален ... ключ в том, что он все еще открыт.
  2. Извлеките информацию из файловой системы на основе этого с помощью отладчика файловой системы.

Использовать Сыщик icat.

sudo icat /dev/rdisk1s2 5484287 > accidentally_deleted_open_file

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

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 чтобы он вышел, когда будет достигнут счет.