
Иногда люди удаляют файлы, которые не должны были, долго выполняющийся процесс все еще держит файл открытым, и восстановление данных с помощью catting /proc/<pid>/fd/N
просто недостаточно круто. Достаточно круто, если бы вы могли "отменить" удаление, запустив какую-нибудь волшебную опцию в ln, которая позволила бы вам повторно связать его с номером inode (восстановленным с помощью lsof).
Я не могу найти никаких инструментов Linux, позволяющих это сделать, по крайней мере, с помощью беглого поиска в Google.
Что у тебя, серверфоул?
EDIT1: Причина, по которой catting файла /proc/<pid>/fd/N
не достаточно крут, заключается в том, что процесс, который все еще держит файл открытым, все еще пишет в него. Удаление удаляет ссылку на inode из пространства имен файловой системы. Мне нужен способ повторного создания ссылки.
EDIT2: 'debugfs ln' работает, но риск слишком высок, так как он загружает необработанные данные файловой системы. Восстановленный файл также безумно непоследователен. Количество ссылок равно нулю, и я не могу добавлять ссылки на него. Мне так хуже, так как я могу просто использовать /proc/<pid>/fd/N
для доступа к данным, не повреждая свою fs.
решение1
Было бы здорово, если бы можно было «отменить» удаление, запустив какую-нибудь волшебную опцию ln, которая позволила бы вам повторно установить ссылку на номер inode (восстановленный с помощью lsof).
Эта удивительность была представлена ln
вверсия 8.0(GNU/coreutils) с -L|--logical
опцией, которая вызывает ln
разыменование /proc/<pid>/fd/<handle>
первого. Так что простое
ln -L /proc/<pid>/fd/<handle> /path/to/deleted/file
достаточно для повторной ссылки на удаленный файл.
решение2
Похоже, вы уже многое поняли, поэтому я не буду вдаваться в излишние подробности. Есть несколько методов поиска inode, и обычно вы можете использовать cat и перенаправить STDOUT. Вы можете использоватьdebugfs
. Выполните эту команду в:
ln <$INODE> FILENAME
Убедитесь, что у вас есть резервные копии файловой системы. Вероятно, вам понадобится запустить fsck после этого. Я успешно протестировал это с inode, в который все еще велась запись, и это действительно работает для создания новой жесткой ссылки на разыменованный inode.
Если файл не связан с неоткрытым файлом в ext3, данные теряются. Я не уверен, насколько это верно, но большая часть моего опыта восстановления данных связана с ext2. Из часто задаваемых вопросов по ext3:
В: Как мне восстановить (отменить удаление) удаленные файлы с моего раздела ext3? На самом деле, вы не можете! Вот что сказал об этом один из разработчиков, Андреас Дилгер:
Чтобы гарантировать, что ext3 сможет безопасно возобновить отсоединение после сбоя, она фактически обнуляет указатели блоков в inode, тогда как ext2 просто отмечает эти блоки как неиспользуемые в битовых картах блоков и отмечает inode как «удалённый», оставляя указатели блоков в покое.
Ваша единственная надежда — выполнить команду grep для поиска частей удаленных файлов и надеяться на лучшее.
В этом вопросе также есть соответствующая информация:
Я перезаписал большой файл пустым на сервере Linux. Могу ли я восстановить существующий файл?
решение3
способ 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 проще и работает так же хорошо, поэтому я предпочитаю именно ее.
решение4
Я не знаю, как именно сделать то, что вы хотите, но я бы сделал следующее:
- Открыть файл RO из другого процесса
- Дождитесь завершения исходного процесса.
- Скопируйте данные из вашего открытого ФД в файл
Не идеально, конечно, но возможно. Другой вариант — поиграться с debugfs (используя команду link
), но это немного страшно на рабочей машине!