Arquivos substituídos podem ser recuperados?

42

Não estou falando de recuperar arquivos excluídos , mas de arquivos substituídos . Ou seja, pelos seguintes métodos:

# move
mv new_file old_file

# copy
cp new_file old_file

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

É possível recuperar alguma coisa se alguma das três ações acima for executada, assumindo que nenhum programa especial esteja instalado na máquina linux?

Pergunta Overflow
fonte
4
Você quer dizer além dos seus backups?
Jasonwryan
@jasonwryan, sim, é claro.
Pergunta Overflow
2
Eu só quero salientar que o seu primeiro exemplo ( mv) é semelhante à exclusão old_file, não a substituição, por isso os métodos (se houver) para recuperar arquivos excluídos, em oposição aos arquivos substituídos, se aplicariam nesse caso. Seus outros dois exemplos de fato substituem um existente old_filee existing_file, respectivamente.
Celada
Todos os três exemplos que você forneceu são implementados excluindo todos os blocos de dados do arquivo original e gravando nos blocos recém-alocados, e o procedimento para recuperar esses dados é o mesmo que recuperar um arquivo excluído. Uma exceção pode ser se os arquivos originais forem extremamente curtos (menores que 60 bytes no ext4), onde os dois últimos exemplos provavelmente tornarão os dados anteriores irrecuperáveis.
Mark Plotnick
1
@MarkPlotnick, de acordo com o comentário de Celada, mvé diferente.
Pergunta Overflow

Respostas:

60

A resposta é "Provavelmente sim, mas depende do tipo e do tempo do sistema de arquivos".

Nenhum desses três exemplos substituirá os blocos de dados físicos do arquivo antigo ou do arquivo existente, exceto por acaso.

  • mv new_file old_file. Isso desvinculará o arquivo antigo. Se houver links físicos adicionais para old_file, os blocos permanecerão inalterados nos links restantes. Caso contrário, os blocos geralmente (dependendo do tipo de sistema de arquivos) serão colocados em uma lista livre. Então, se for mvnecessário copiar (ao contrário de apenas mover as entradas do diretório), novos blocos serão alocados como mvgravações.

    Esses blocos recém-alocados podem ou não ser os mesmos que foram liberados . Em sistemas de arquivos como o UFS , os blocos são alocados, se possível, do mesmo grupo de cilindros que o diretório em que o arquivo foi criado. Portanto, há uma chance de desvincular um arquivo de um diretório e criar um arquivo nesse mesmo diretório ( e sobrescreva) alguns dos mesmos blocos que foram liberados. É por isso que o conselho padrão para as pessoas que removerem acidentalmente um arquivo é não gravar novos dados nos arquivos em sua árvore de diretórios (e de preferência não em todo o sistema de arquivos) até que alguém possa tentar a recuperação do arquivo.

  • cp new_file old_filefará o seguinte (você pode usar stracepara ver as chamadas do sistema):

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

    O sinalizador O_TRUNC fará com que todos os blocos de dados sejam liberados, assim como mvacima. E, como acima, eles geralmente serão adicionados a uma lista gratuita e podem ou não ser reutilizados pelas gravações subsequentes feitas pelo cpcomando.

  • vi existing_file. Se vifor realmente vim, o :xcomando faz o seguinte:

    desvincular ("arquivo_existente ~") = -1 ENOENT (arquivo ou diretório inexistente)
    renomear ("arquivo_existente", "arquivo_existente ~") = 0
    open ("arquivo_existente", O_WRONLY | O_CREAT | O_TRUNC, 0664) = 3

    Portanto, ele nem remove os dados antigos; os dados são preservados em um arquivo de backup.

    No FreeBSD, vidoes open("existing_file",O_WRONLY|O_CREAT|O_TRUNC, 0664), que terá a mesma semântica que cpacima.


Você pode recuperar alguns ou todos os dados sem programas especiais; tudo que você precisa é grepe dd, e acesso ao dispositivo bruto.

Para arquivos de texto pequenos, o grepcomando único na resposta de @Steven D na pergunta que você vinculou é a maneira mais fácil:

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

Mas para arquivos maiores que podem estar em vários blocos não contíguos, faço o seguinte:

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

que fornecerá o deslocamento em bytes da linha correspondente. Siga isso com uma série de ddcomandos, começando com

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

Você também gostaria de ler alguns blocos antes e depois desse bloco. No UFS, os blocos de arquivos geralmente têm 8 KB e geralmente são alocados de maneira bastante contígua, sendo os blocos de um único arquivo intercalados alternadamente com blocos de 8 KB de outros arquivos ou espaço livre. A cauda de um arquivo no UFS é de até 7 fragmentos de 1 KB, que podem ou não ser contíguos.

Obviamente, em sistemas de arquivos que compactam ou criptografam dados, a recuperação pode não ser tão simples.


Na verdade, existem muito poucos utilitários no Unix que sobrescrevem os blocos de dados de um arquivo existente. Um que vem à mente é dd conv=notrunc. Outro é shred.

Mark Plotnick
fonte
3
Obrigado por explicar a mecânica interna das três operações diferentes. Isso é realmente útil!
Pergunta Overflow
btrfsé bastante resistente a arquivos excluídos. Ele costuma usar blocos de maneira alternada, portanto, se você tiver espaço suficiente no dispositivo, o arquivo não será substituído por um longo tempo. Veja aqui
pqnet
como obter o bloco de texto anterior e o que o skip faz?
unixit
@Islam Quando você der o skip=parâmetro dd , em vez de ler desde o início da entrada, ele pulará esse número de blocos. Um bloco tem 512 bytes por padrão, mas pode ser alterado com o bs=parâmetro
precisa saber é o seguinte
1
@Islam Para obter o bloco de texto anterior, sugiro fornecer um skip=valor que seja 1 bloco (512 bytes) a menos. No meu exemplo $(expr 13813610612 / 512 - 1),. Se isso não conseguir o que você deseja, tente novamente subtraindo 16 ou 32, que analisará as áreas com 8192 e 16384 bytes a menos; os arquivos geralmente são alocados em blocos de 8192 bytes. Se você estiver tentando recuperar um arquivo maior, tente contagens maiores para economizar tempo. Eu costumo usar count=16e olhar para o resultado em um editor como o emacsque não se importa se alguns dos dados não são texto.
precisa saber é o seguinte
6

Vou dizer não (com um asterisco gigante).

Pense em como os dados são colocados em um disco. Você tem blocos que contêm dados e apontam para o próximo bloco (se houver um).

Quando você sobrescreve os dados, está alterando o conteúdo do bloco (e se estiver estendendo o arquivo todo o marcador final). Portanto, nada deve poder ser recuperado (veja abaixo).

Se você diminuir o arquivo, estará perdendo os blocos antigos e eles serão reciclados em breve. Se você é um programador, pense em uma lista vinculada na qual você "perde" metade da sua lista sem fazer uma exclusão / exclusão. Esses dados ainda estão lá, mas boa sorte em encontrá-los.

Algo que pode ser interessante para pensar é a fragmentação.

A fragmentação ocorre quando você tem "furos" de dados não contíguos no disco. Isso pode ser causado pela modificação de arquivos que os estendem ou encurtam, e eles não cabem mais no local original do disco.

No caso de um arquivo crescer além do tamanho original (ele precisa ser movido neste momento), dependendo do seu sistema de arquivos, você pode copiar o arquivo inteiro para um novo local onde os dados antigos ainda estariam lá (mas marcados como livres) ou apenas altere o ponteiro final antigo e faça com que aponte para um novo local (isso levará a uma surra).

Para resumir a história, seus dados provavelmente estão perdidos (sem passar por um processo forense extremo em que você os observa sob um microscópio); no entanto, há uma chance de que ainda esteja lá.

SailorCire
fonte
1
Sua resposta pressupõe que um sistema de arquivos sem cópia em gravação, baseado em bloco, como ext4ou xfsesteja em uso. Com a cópia em sistemas de arquivos de gravação como zfse btrfsvocê nunca está "alterando o conteúdo do bloco"; esses sistemas de arquivos sempre usam novos blocos para conter novos dados. Além disso, os sistemas de arquivos baseados em log, como jffs2também, sempre gravam novos dados em novos locais (não "blocos", esses sistemas de arquivos não são baseados em blocos). Dito isto, isso não significa que é fácil descobrir onde estão os dados antigos e fazê-lo antes que o espaço seja reciclado. Assim, a sua resposta, que não é, ainda está correto
Celada
@Celada Thanks! Achei isso muito informativo. Não tive tempo de ver como o btrfs ou o zfs funciona, mas sabia que eles existem.
SailorCire
2

Verifique se você possui espaço em disco suficiente em / var / tmp ou em algum lugar grande.

Experimentar

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

onde / dev / sda1 seria seu disco no seu sistema.

Em seguida, procure no meu arquivo recuperado sua string.

Pode estar na maioria das vezes, se você encontrar espaços de linhas, colchetes, sistemas em falta, etc.

Use uma palavra de pesquisa do seu arquivo que seja bastante unqiue ou string que reduzirá a quantidade de dados no arquivo. Se você procurar por uma palavra como "eco", receberá várias seqüências de caracteres, pois o sistema terá muitos arquivos com a palavra eco neles.

AndyM
fonte
0

Eu havia sobrescrito um arquivo de texto (VQ1.txt) com dados de teste de 12 horas :( Uma noção que unix salva a versão anterior do arquivo no formato text.txt ~, me fez procurar na pasta que continha o arquivo sobrescrito com $ -ll Full lista mostrou VQ1.txt ~ que tinha meus dados 'perdidos'!

$ 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
fonte
4
Isso não é mais um recurso de determinados editores de texto, em vez do Unix em geral? Não estou ciente de um sistema de arquivos que salva versões antigas de arquivos dessa maneira.
Joey
0

TL; DR - Se o arquivo substituído ainda estiver sendo mantido aberto por um processo em execução, esta postagem no blog poderá salvar seu bacon:

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

Nele, ele fala sobre arquivos excluídos , mas tive sorte mesmo com um arquivo que foi sobrescrito pelo rsync. E estou falando de um arquivo de 60 GB substituído por um de 4 MB e consegui recuperar o original porque, felizmente, não havia parado o processo de execução que o mantinha aberto.

completo
fonte