Можно ли восстановить перезаписанные файлы?

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, да, конечно.
Вопрос переполнен
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для просмотра системных вызовов):

    open ("old_file", O_WRONLY | O_TRUNC) = 4

    Флаг O_TRUNC приведет к освобождению всех блоков данных, как это mvделалось выше. И, как указано выше, они, как правило, добавляются в свободный список и могут или не могут быть повторно использованы последующими записями, выполненными cpкомандой.

  • vi existing_file, Если viэто на самом деле vim, :xкоманда делает следующее:

    unlink ("существующий_файл ~") = -1 ENOENT (нет такого файла или каталога)
    переименовать ("существующий_файл", "существующий_файл ~") = 0
    open ("существующий_файл", 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

Я собираюсь сказать нет (с гигантской звездочкой).

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

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

Если вы укоротите файл, вы потеряете старые блоки, и они скоро будут переработаны. Если вы программист, подумайте о связанном списке, в котором вы «теряете» половину списка, не делая свободного / удаления. Эти данные все еще там, но удачи в их поиске.

Что-то, о чем может быть интересно подумать, это фрагментация.

Фрагментация происходит, когда на вашем диске есть «дыры» несмежных данных. Это может быть вызвано изменением файлов таким образом, что вы расширяете или укорачиваете их, и они больше не помещаются в исходное место на диске.

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

Короче говоря, ваши данные, вероятно, потеряны (без прохождения экстремального судебного процесса, когда вы смотрите на них под микроскопом); Однако есть вероятность, что он все еще там.

SailorCire
источник
1
Ваш ответ предполагает, что основанная на блоках файловая система без копирования при записи, такая как ext4или xfsиспользуется. С копированием при записи файловых систем, таких как zfsи btrfsвы на самом деле никогда не «меняете содержимое блока»; эти файловые системы всегда используют новые блоки для хранения новых данных. Кроме того, файловые системы, основанные на журналах, jffs2также всегда записывают новые данные в новые местоположения (не «блоки», эти файловые системы не основаны на блоках). Это, как говорится, не означает, что легко найти, где хранятся старые данные, и сделать это до того, как пространство будет использовано повторно. Таким образом, ваш ответ, который нет, по-прежнему правильный
Celada
@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 будет вашим диском в вашей системе.

Затем найдите строку my-recovered-file для вашей строки.

В основном это может быть там, если вы найдете его, проверьте наличие пропущенных строк, скобок, системных символов и т. Д.

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

AndyM
источник
0

Я переписал текстовый файл (VQ1.txt) с тестовыми данными стоимостью 12 часов :( Из-за того, что unix сохраняет предыдущую версию файла в формате text.txt ~, я перешел в папку, содержащую перезаписанный файл, с $ -ll Full список показал 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
catsat
источник
4
Разве это не особенность некоторых текстовых редакторов вместо Unix в целом? Я не знаю о файловой системе, которая таким образом сохраняет старые версии файлов.
Джои
0

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

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

В нем говорится об удаленных файлах, но мне повезло с этим, даже с файлом, который был перезаписан rsync. И я говорю о 60 ГБ файле, перезаписанном 4 МБ, и я смог восстановить оригинал, потому что, к счастью, я не остановил запущенный процесс, который держал его открытым.

FULV
источник