Peut-on récupérer des fichiers écrasés?

42

Je ne parle pas de récupérer des fichiers supprimés , mais des fichiers écrasés . À savoir par les méthodes suivantes:

# move
mv new_file old_file

# copy
cp new_file old_file

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

Est-il possible de récupérer quoi que ce soit si l'une des trois actions ci-dessus est effectuée en supposant qu'aucun programme spécial n'est installé sur la machine Linux?

Débordement de la question
la source
4
Vous voulez dire en dehors de vos sauvegardes?
jasonwryan
@jasonwryan, oui, bien sûr.
Question débordement
2
Je tiens simplement à souligner que votre premier exemple ( mv) s'apparente à la suppression old_fileet non à son écrasement. Les méthodes (le cas échéant) de récupération de fichiers supprimés, par opposition à des fichiers écrasés, s'appliqueraient dans ce cas. Vos deux autres exemples écrasent effectivement un existant old_fileet existing_file, respectivement.
Celada
Les trois exemples que vous avez fournis sont implémentés en supprimant tous les blocs de données du fichier d'origine et en écrivant dans les blocs récemment alloués. La procédure de récupération de ces données est identique à celle d'un fichier supprimé. Une exception pourrait être si les fichiers originaux sont excessivement courts (moins de 60 octets sur ext4), où les deux derniers exemples rendent probablement les données précédentes irrécupérables.
Mark Plotnick
1
@ MarkPlotnick, selon le commentaire de Celada, mvest différent.
Question débordement

Réponses:

60

La réponse est "Probablement oui, mais cela dépend du type de système de fichiers et du moment."

Aucun de ces trois exemples n'écrase les blocs de données physiques de old_file ou existing_file, sauf par hasard.

  • mv new_file old_file. Cela dissociera old_file. S'il existe des liens physiques supplémentaires vers old_file, les blocs resteront inchangés dans ces liens restants. Sinon, les blocs seront généralement (cela dépend du type de système de fichiers) placés sur une liste libre. Ensuite, si la mvcopie doit être copiée (par opposition à un simple déplacement des entrées du répertoire), de nouveaux blocs seront attribués en mvécriture.

    Ces blocs nouvellement alloués peuvent être ou ne pas être les mêmes que ceux qui viennent d'être libérés . Sur les systèmes de fichiers comme UFS , les blocs sont alloués, si possible, du même groupe de cylindres que le répertoire dans lequel le fichier a été créé. Il est donc possible que la dissociation d’un fichier d’un répertoire et la création d’un fichier dans ce même répertoire soient réutilisées ( et écraser) certains des mêmes blocs qui viennent d'être libérés. C'est pourquoi le conseil standard aux personnes qui suppriment accidentellement un fichier est de ne pas écrire de nouvelles données dans les fichiers de leur arborescence de répertoires (et de préférence pas dans le système de fichiers complet) jusqu'à ce que quelqu'un puisse tenter de récupérer le fichier.

  • cp new_file old_filefera ce qui suit (vous pouvez utiliser stracepour voir les appels système):

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

    L'indicateur O_TRUNC entraînera la libération de tous les blocs de données, comme mvprécédemment. Et comme ci-dessus, ils seront généralement ajoutés à une liste libre et pourront ou non être réutilisés lors des écritures ultérieures effectuées par la cpcommande.

  • vi existing_file. Si vic'est réellement vim, la :xcommande fait ce qui suit:

    unlink ("existing_file ~") = -1 ENOENT (aucun fichier ou répertoire de ce type)
    renommer ("fichier_existant", "fichier_existant ~") = 0
    open ("fichier_existant", O_WRONLY | O_CREAT | O_TRUNC, 0664) = 3

    Donc, il ne supprime même pas les anciennes données; les données sont conservées dans un fichier de sauvegarde.

    Sous FreeBSD, vido open("existing_file",O_WRONLY|O_CREAT|O_TRUNC, 0664), qui aura la même sémantique que cpci-dessus.


Vous pouvez récupérer tout ou partie des données sans programmes spéciaux; tout ce dont vous avez besoin est grepet dd, et un accès au périphérique brut.

Pour les petits fichiers texte, la seule grepcommande dans la réponse de @Steven D dans la question à laquelle vous êtes lié est la manière la plus simple:

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

Mais pour les fichiers plus volumineux pouvant se trouver dans plusieurs blocs non contigus, voici ce que je fais:

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

qui vous donnera le décalage en octets de la ligne correspondante. Suivez ceci avec une série de ddcommandes, en commençant par

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

Vous voudriez aussi lire quelques blocs avant et après ce bloc. Sur UFS, les blocs de fichiers font généralement 8 Ko et sont généralement alloués de manière relativement contiguë, les blocs d’un fichier étant entrelacés en alternance avec des blocs de 8 Ko provenant d’autres fichiers ou de l’espace disponible. La queue d'un fichier sur UFS est constituée de 7 fragments de 1 Ko maximum, pouvant être contigus ou non.

Bien entendu, sur les systèmes de fichiers qui compressent ou chiffrent des données, la récupération peut ne pas être aussi simple.


Il existe actuellement très peu d'utilitaires dans Unix qui écraseront les blocs de données d'un fichier existant. Un qui vient à l'esprit est dd conv=notrunc. Un autre est shred.

Mark Plotnick
la source
3
Merci d’avoir expliqué la mécanique interne des trois opérations différentes. C'est vraiment utile!
Question débordement
btrfsest assez résistant aux fichiers supprimés. Il a tendance à utiliser des blocs tour à tour. Par conséquent, si vous disposez de suffisamment d'espace sur le périphérique, le fichier ne sera pas écrasé pendant une longue période. Voir ici
pqnet
comment obtenir le bloc de texte précédent et que fait skip?
Unixit
@Islam Lorsque vous donnez le skip=paramètre à dd , au lieu de lire depuis le début de l'entrée, il saute ce nombre de blocs. Un bloc contient 512 octets par défaut, mais peut être modifié avec le bs=paramètre.
Mark Plotnick le
1
@Islam Pour obtenir le bloc de texte précédent, nous suggérons de donner une skip=valeur inférieure à 1 bloc (512 octets). Dans mon exemple, $(expr 13813610612 / 512 - 1). Si cela ne donne pas ce que vous voulez, essayez à nouveau en soustrayant 16 ou 32, ce qui correspond aux zones de moins de 8192 octets et 16 384 octets; les fichiers sont souvent alloués en morceaux de 8192 octets. Si vous essayez de récupérer un fichier plus volumineux, essayez des comptes plus volumineux pour gagner du temps. J'utilise count=16et regarde habituellement le résultat dans un éditeur du genre, emacsce qui ne me dérange pas si certaines données ne sont pas du texte.
Mark Plotnick le
6

Je vais dire non (avec un astérisque géant).

Pensez à la manière dont les données sont déposées sur un disque. Vous avez des blocs qui contiennent des données et pointent sur le bloc suivant (s'il en existe un).

Lorsque vous écrasez des données, vous modifiez le contenu du bloc (et, si vous étendez le fichier, tous les marqueurs de fin). Donc, rien ne devrait pouvoir être récupéré (voir ci-dessous).

Si vous raccourcissez le fichier, vous perdez les anciens blocs et ils seront bientôt recyclés. Si vous êtes programmeur, pensez à une liste chaînée dans laquelle vous "perdez" la moitié de votre liste sans supprimer / supprimer. Ces données sont toujours là, mais bonne chance pour les trouver.

Il est intéressant de penser à la fragmentation.

La fragmentation se produit lorsque vous avez des "trous" de données non contiguës sur votre disque. Cela peut être provoqué par la modification de fichiers tels que vous les étendez ou les raccourcissez et qu'ils ne tiennent plus à leur emplacement d'origine sur le disque.

Si un fichier dépasse sa taille d'origine (il doit être déplacé à ce stade), en fonction de votre système de fichiers, vous pouvez copier l'intégralité du fichier dans un nouvel emplacement où les anciennes données seraient toujours présentes (mais marquées comme étant gratuites). ou vous changez simplement l’ancien pointeur de fin et le faites pointer vers un nouvel emplacement (cela conduirait à une bagarre).

En bref, vos données sont probablement perdues (sans passer par un processus médico-légal extrême où vous les regardez au microscope); Cependant, il y a une chance qu'il soit toujours là.

SailorCire
la source
1
Votre réponse suppose qu’un système de fichiers sans copie sur écriture, basé sur des blocs, tel que ext4ou xfsest utilisé. Avec la copie sur des systèmes de fichiers en écriture tels que zfset btrfsvous ne "changez jamais le contenu du bloc"; ces systèmes de fichiers utilisent toujours de nouveaux blocs pour contenir de nouvelles données. En outre, les systèmes de fichiers logarithmiques jffs2écrivent toujours de nouvelles données dans de nouveaux emplacements (pas des "blocs", ces systèmes de fichiers ne sont pas basés sur des blocs). Cela étant dit, cela ne signifie pas qu'il soit facile de localiser les anciennes données et de le faire avant que l'espace ne soit recyclé. Donc, votre réponse, qui est non, est toujours correcte
Celada
@Celada Merci! J'ai trouvé cela très instructif. Je n'ai pas eu le temps de regarder comment btrfs ou zfs fonctionne, mais je savais qu'ils existaient.
SailorCire
2

Assurez-vous de disposer de suffisamment d’espace disque dans / var / tmp ou dans un autre emplacement.

Essayer

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

où / dev / sda1 serait votre disque sur votre système.

Ensuite, recherchez la chaîne dans mon fichier récupéré.

Il pourrait être la plupart du temps là - bas, si vous trouvez vérifier linespaces manquantes, crochets, etc. sysmbols

Utilisez un mot de recherche de votre fichier qui est assez moche ou une chaîne qui réduira la quantité de données dans le fichier. Si vous recherchez un mot tel que "echo", vous récupérerez un grand nombre de chaînes car le système contiendra de nombreux fichiers contenant le mot echo.

AndyM
la source
0

J'avais écrasé un fichier texte (VQ1.txt) avec 12 h valant des données de test :( Une idée qu'Unix enregistre la version précédente du fichier au format text.txt ~, m'a amené à consulter le dossier contenant le fichier écrasé avec $ -ll Full La liste montrait VQ1.txt ~ qui avait mes données 'perdues'!

$ 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
la source
4
N’est-ce pas plutôt une caractéristique de certains éditeurs de texte au lieu d’Unix en général? Je ne connais pas de système de fichiers qui enregistre les anciennes versions de fichiers de cette manière.
Joey
0

TL; DR - Si le fichier écrasé est toujours maintenu ouvert par un processus en cours, cet article de blog peut enregistrer votre bacon:

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

Dans ce document, il est question de fichiers supprimés , mais j’ai eu de la chance, même avec un fichier écrasé par rsync. Et je parle d’un fichier de 60 Go écrasé par un de 4 Mo, et j’ai pu récupérer l’original car, heureusement, je n’avais pas arrêté le processus en cours qui le maintenait ouvert.

fulv
la source