Чи можна відновити перезаписані файли?


42

Я говорю не про відновлення видалених файлів , а про перезаписані файли. А саме такими методами:

# move
mv new_file old_file

# copy
cp new_file old_file

# edit
vi existing_file
> D
> i new_content
> :x

Чи можливо отримати що-небудь, якщо виконано будь-яке з перерахованих вище трьох дій, якщо на машині Linux не встановлено спеціальних програм?


4
Ви маєте на увазі, крім ваших резервних копій?
jasonwryan

@jasonwryan, так, звичайно.
Переповнення запитань

2
Я просто хочу зазначити, що ваш перший приклад ( mv) схожий на видалення old_file, а не його перезапис, тому методи (якщо такі існують) для відновлення видалених файлів, на відміну від перезаписаних файлів, застосовуватимуться в цьому випадку. Ваші інші два приклади дійсно перезаписують існуючі old_fileта existing_file, відповідно.
Селада

Усі три надані вами приклади реалізуються шляхом видалення всіх блоків даних оригінального файлу та запису до новопризначених блоків, а процедура відновлення даних така ж, як і відновлення видаленого файлу. Виняток може бути, якщо оригінальні файли дуже короткі (коротше 60 байт на ext4), де два останні приклади, ймовірно, роблять попередні дані не підданими.
Марк Плотнік

1
@MarkPlotnick, за коментарем Селади, mvвідрізняється.
Переповнення запитань

Відповіді:


60

Відповідь - "Мабуть, так, але це залежить від типу файлової системи та термінів".

Жоден із цих трьох прикладів не замінить фізичні блоки даних old_file або існуючий_file, за винятком випадковості.

  • mv new_file old_file. Це дозволить від’єднати old_file. Якщо є додаткові жорсткі посилання на old_file, блоки залишатимуться незмінними в цих решти посилань. В іншому випадку блоки, як правило, (це залежить від типу файлової системи), будуть розміщені у вільному списку. Тоді, якщо mvпотрібно копіювання (протилежне лише переміщенню записів каталогів), нові блоки будуть виділятися як mvзаписи.

    Ці щойно виділені блоки можуть бути або не бути тими самими, що були звільнені . У файлових системах, таких як UFS , блоки розподіляються, якщо можливо, із тієї ж групи циліндрів, що і каталог, у якому створено файл. Отже, є ймовірність, що від’єднання файлу з каталогу та створення файлу в тому самому каталозі будуть повторно використані ( і перезаписати) деякі з тих самих блоків, які щойно звільнили. Ось чому стандартна порада для людей, які випадково видаляють файл, - не записувати жодних нових даних у файли у своєму дереві каталогів (а краще не у всю файлову систему), поки хтось не може спробувати відновити файл.

  • cp new_file old_fileзробить наступне (ви можете використовувати straceдля перегляду системних дзвінків):

    відкрити ("old_file", O_WRONLY | O_TRUNC) = 4

    Прапор O_TRUNC призведе до звільнення всіх блоків даних, як mvі раніше. І як зазначено вище, вони, як правило, будуть додані до вільного списку і можуть або не можуть повторно використовуватися наступними записами, виконаними cpкомандою.

  • vi existing_file. Якщо viнасправді vim, то :xкоманда виконує наступні дії :

    unlink ("існуючий_файл ~") = -1 ENOENT (немає такого файлу чи каталогу)
    перейменувати ("існуючий_файл", "існуючий_файл ~") = 0
    відкрити ("існуючий_файл", O_WRONLY | O_CREAT | O_TRUNC, 0664) = 3

    Таким чином, він навіть не видаляє старі дані; дані зберігаються у резервному файлі.

    У FreeBSD - viце те open("existing_file",O_WRONLY|O_CREAT|O_TRUNC, 0664), що матиме ту саму семантику, як cpі вище.


Ви можете відновити деякі чи всі дані без спеціальних програм; все , що вам потрібно , grepі dd, а також доступ до вихідного пристрою.

Для невеликих текстових файлів найпростішим способом є одна grepкоманда у відповіді від @Steven D у запитанні, до якого ви пов’язані.

grep -i -a -B100 -A100 'text in the deleted file' /dev/sda1

Але для великих файлів, які можуть бути в декількох непоміжних блоках, я роблю це:

grep -a -b "text in the deleted file" /dev/sda1
13813610612:this is some text in the deleted file

що дасть вам зміщення у байтах відповідного рядка. Виконайте це з низкою ddкоманд, починаючи з

dd if=/dev/sda1 count=1 skip=$(expr 13813610612 / 512)

Ви також хочете прочитати деякі блоки до і після цього блоку. На UFS файлові блоки зазвичай складають 8 КБ і зазвичай виділяються досить безперервно, блоки одного файлу перемежовуються по черзі з блоками 8 КБ з інших файлів або вільного місця. Хвіст файлу на UFS має до 7 фрагментів 1 КБ, які можуть бути, а можуть і не бути суміжними.

Звичайно, у файлових системах, які стискають або шифрують дані, відновлення не може бути таким простим.


Насправді дуже мало утиліт у Unix, які перезаписують блоки даних існуючого файлу. Те, що спадає на думку, - це dd conv=notrunc. Інша є shred.


3
Дякую за пояснення внутрішньої механіки трьох різних операцій. Це справді корисно!
Переповнення запитань

btrfsдосить стійкий до видалених файлів. Він, як правило, використовує блоки в круговій формі, тому, якщо у вас достатньо місця на пристрої, файл не буде перезаписаний протягом тривалого часу. Дивіться тут
pqnet

як отримати попередній текстовий блок і що робити пропуск?
unixit

@Islam Коли ви даєте skip=параметр dd , то замість зчитування з початку введення він пропустить цю кількість блоків. Блок становить 512 байт за замовчуванням, але його можна змінити за допомогою bs=параметра.
Марк Плотнік

1
@Islam Щоб отримати попередній текстовий блок, я б запропонував вказати skip=значення, яке на 1 блок (512 байт) менше. У моєму прикладі $(expr 13813610612 / 512 - 1). Якщо це не отримає те, що ви хочете, спробуйте ще раз, віднімаючи 16 або 32, які будуть дивитися на області, на 8192 і 16384 байт менше; Файли часто виділяються в 8192-байтних фрагментах. Якщо ви намагаєтеся відновити більший файл, спробуйте збільшити кількість, щоб заощадити час. Зазвичай я використовую count=16і переглядаю результат у такому редакторі, emacsякий не проти, якщо частина даних не є текстовою.
Марк Плотнік

6

Я скажу «ні» (з гігантською зірочкою).

Подумайте, як дані лежать на диску. У вас є блоки, які містять дані і вказують на наступний блок (якщо такий є).

Коли ви перезаписуєте дані, ви змінюєте вміст блоку (і якщо ви розширюєте файл всім кінцевим маркером). Таким чином, нічого не має бути в змозі відновити (див. Нижче).

Якщо ви скоротите файл, то ви втрачаєте старі блоки, і вони незабаром переробляються. Якщо ви програміст, придумайте пов’язаний список, де ви «втрачаєте» половину свого списку, не роблячи безкоштовного / видалення. Ці дані все ще є, але удача їх знайшла.

Щось, що може бути цікавим подумати, - це фрагментація.

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

У випадку, якщо файл зросте з початковим розміром (його потрібно перемістити в цей момент), залежно від вашої файлової системи ви можете скопіювати весь файл у нове місце, де старі дані все ще будуть там (але позначені як вільні) або ви просто поміняєте старий кінцевий покажчик і вкажете його на нове місце (це призведе до обмолоту).

Якщо коротко розповісти, ваші дані, ймовірно, втрачаються (не проходячи екстремальний криміналістичний процес, коли ви дивитесь на них під мікроскопом); проте є ймовірність, що він все-таки є.


1
Ваша відповідь передбачає припущення, що файлова система без копіювання на запис, заснована на блоці, наприклад, використовується ext4або xfsвикористовується. З копією на файлові системи запису, такі як, zfsі btrfsви насправді ніколи не «змінюєте вміст блоку»; ці файлові системи завжди використовують абсолютно нові блоки, щоб містити нові дані. Крім того, файлові системи на основі журналів, як-от, jffs2також завжди записують нові дані в нові місця (не "блоки", ці файлові системи не є блоковими). Однак, це не означає, що легко знайти місце, де живуть старі дані, і зробити це перед тим, як простір утилізується. Тож ваша відповідь, яка є ні, все ще правильна
Селада,

@Celada Дякую! Я знайшов це дуже інформативно. У мене не було часу подивитися, як працюють btrfs чи zfs, але я знав, що вони існують.
SailorCire

2

Переконайтеся, що у вас є достатньо місця на диску / var / tmp або десь великий.

Спробуйте

 grep -i -a -B100 -A100 'a string unique to your file' /dev/sda1 |
 strings > /var/tmp/my-recovered-file

де / dev / sda1 буде вашим диском у вашій системі.

Потім шукайте мій-відновлений файл для вас рядка.

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

Скористайтеся пошуковим словом у вашому файлі, яке є досить unqiue або рядком, що зменшить кількість даних у файлі. Якщо ви будете шукати таке слово, як "echo", ви отримаєте безліч рядків, оскільки система матиме багато файлів зі словом echo в них.


0

Я перезаписав текстовий файл (VQ1.txt) з тестовими даними на 12 годин :( Поняття, що Unix зберігає попередню версію файлу у форматі text.txt ~, змусило мене заглянути в папку, що містить перезаписаний файл з повною версією $ -ll У списку показано VQ1.txt ~, в якому були мої «втрачені» дані!

$ cat VQ1.txt~  
Start time at: Thu Apr  2 18:07:23 PDT 2015
User, KW: 12hrFA_OEM_HelloVoiceQ
Test Case: 
Detection:  1, 1, 04-03 01:07:00.673 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1
Detection:  2, 1, 04-03 01:09:04.813 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1
Detection:  3, 1, 04-03 04:09:26.023 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1
Detection:  4, 1, 04-03 04:11:29.893 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1
Detection:  5, 1, 04-03 07:12:27.013 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1
Detection:  6, 1, 04-03 07:14:30.803 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1
Detection:  7, 1, 04-03 08:37:13.113 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1
Detection:  8, 1, 04-03 10:21:23.533 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1
Detection:  9, 1, 04-03 10:23:27.733 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1
Detection:  10, 1, 04-03 13:23:47.893 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1
Detection:  11, 1, 04-03 13:25:52.203 D/MultiKeywordBdctReceiver( 1743): vs status 258 : 2 : 1

12hrFA_OEM_HelloVoiceQ,  
KW detect count: 11

4
Хіба це не особливість певних текстових редакторів замість Unix взагалі? Мені невідома файлова система, яка таким чином зберігає старі версії файлів.
Joey

0

TL; DR - Якщо перезаписаний файл все ще залишається відкритим у запущеному процесі, то ця публікація в блозі може зберегти ваш бекон:

https://www.linux.com/news/bring-back-deleted-files-lsof/

У ньому йдеться про видалені файли, але мені пощастило навіть із файлом, який перезаписав rsync. І я кажу про файл розміром 60 Гб, перезаписаний на 4 Мб, і мені вдалося відновити оригінал, тому що, на щастя, я не зупинив запущений процес, який підтримував його відкритим.

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