Повторна посилання на видалений файл


33

Іноді люди видаляють файли, які вони не повинні, тривалий процес все ще має відкритий файл, а відновлення даних шляхом котирування /proc/<pid>/fd/Nпросто не є приголомшливим. Досить дивовижним було б, якби ви могли "скасувати" видалення, запустивши якусь магічну опцію до ln, яка дозволить вам повторно зв’язатися з номером inode (відновлений через lsof).

Я не можу знайти жодних інструментів Linux, щоб це зробити, принаймні з помірним Googling.

Що ти маєш, сервер за замовчуванням?

EDIT1: Причина отримання файлу з файлу /proc/<pid>/fd/Nнедостатньо приголомшлива, це те, що процес, який відкриває файл, все ще пише на нього. Видалення видаляє посилання на inode з простору імен файлової системи. Те, що я хочу, - це спосіб відновлення довідки.

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

Відповіді:


14

Досить дивовижним було б, якби ви могли "скасувати" видалення, запустивши якусь магічну опцію до 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

достатньо для відновлення видаленого файлу.


7
Це не працює; якщо файл буде видалений, він вийде з ладу.
Випадково832

1
Ні, не буде. Я регулярно використовую це для відновлення видалених, але все-таки відкритих файлів. Але вам потрібно переконатися, що нове /path/to/deleted/fileзнаходиться у тій же файловій системі , що і файл, який був безпосередньо перед його видаленням, інакше це - справді - не вдасться. (Ви можете отримати старий шлях за допомогою ls -l /proc/<pid>/fd/<handle>)
tnimeu

2
Цей функціонал (див. Це запитання та відповідь) було спеціально відхилено як ризик для безпеки [до гіпотетичної схеми безпеки, яка обертається навколо привілейованого процесу, що надає вашому процесу обробку файлу лише для читання у вашому файлі, але в іншому випадку не маєте доступу до ]; Я спробував це (хоча з невеликою програмою С безпосередньо використовувати відповідний системний виклик), і це не вийшло.
Випадково832

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, який все ще записується, і він працює, щоб створити нове жорстке посилання на dereferenced inode.

Якщо файл від’єднано з незакритим файлом у ext3, дані втрачаються. Я не впевнений, наскільки це послідовно вірно, але більшість мого досвіду відновлення даних стосується ext2. З FAQ3 ext3:

Питання: Як я можу відновити (видалити) видалені файли зі свого розділу ext3? Насправді, ви не можете! Про це сказав один з розробників Андреас Ділгер:

Щоб забезпечити, що ext3 може безпечно відновити від’єднання після збою, він фактично нульовує блокові покажчики в inode, тоді як ext2 просто позначає ці блоки як невикористані в бітових картах блоку і позначає inode як "видалений" і залишає блок вказівники поодинці.

Ваша єдина надія - "прогрібати" частину файлів, які були видалені, і сподіватися на найкраще.

У цьому питанні також є відповідна інформація:

Я перезаписав великий файл із порожнім на сервері linux. Чи можу я відновити наявний файл?


Коментар, сподіваємось, видалено, оскільки він не був поважним.
mdpc

1
Що стосується видаленого, але все ще відкритого файлу, я не думаю, що він би нульовий покажчик у inode. Крім того, замість використання "ln" у налагодженнях я використовував би "unel", щоб кількість посилань inode правильно оновлювалася.
Марк Вагнер

Я не мав намір на це натякнути, ембо. Це не так, я перевірив продуктивність. Я уточнив свою мову.
Warner

Розумний, але пошкоджує мою файлову систему. :)
mbac32768

Це єдине рішення для сценарію, як ви його описуєте. Маніпулювання файловою системою на низькому рівні, що встановлюється rw та активно записується на неї, швидше за все, спричинить корупцію майже у всіх сценаріях.
Warner

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 простіший і працює так само добре, тому це є моєю перевагою.


3

Я не знаю, як робити саме те, що ти хочеш, але що я би робив:

  • Відкрийте файл RO з іншого процесу
  • Зачекайте вихід оригінального процесу
  • Скопіюйте дані з відкритого FD у файл

Очевидно, але не ідеально, але можливо. Інший варіант - пограти з налагодженнями (за допомогою linkкоманди), але це начебто страшно на виробничій машині!


Команда посилання debugfs взагалі не підтримує цей випадок використання.
mbac32768

tldp.org/HOWTO/Ext2fs-Undeletion-11.html пропонує зробити це. Я не пробував цього, але це здається розумним.
Білл Вайс

linkне працював у моєму тестуванні, але lnробив.
Warner

3

Зустрівшись із тією ж проблемою і сьогодні. Найкраще, що я міг придумати, - це бігати

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

в сеансі tmux / screen, поки процес не закінчиться.


2
Посилання на оригінальні файли, як у прийнятій відповіді, має працювати.
Кріс S

1
На це питання немає прийнятої відповіді, до якого ви звертаєтесь?
Хамман Самуель

Чи не потрібно це перенаправлення ( >) на видалений файл?
ncasas

1

Цікаве запитання. Інтерв'юер задав те саме питання і мені на співбесіді з роботи. Я сказав йому, що це непростий спосіб зробити це, і взагалі не варте часу та зусиль. Я його запитав, що він вважає рішенням цього питання ...

  1. Використовуйте lsof для пошуку номера inode на диску для процесу, оскільки він все ще з’явиться, навіть якщо файл був видалений ... Ключ у тому, що він все ще відкритий.
  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's, з pvкинутим:

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

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.