Acabei de “mover” um diretório de 49 GB para um caminho de arquivo inválido. É possível restaurar o estado original dos arquivos?

58

Eu tenho (bem, eu tinha ) um diretório:

/media/admin/my_data

Tinha aproximadamente 49 GB de tamanho e continha dezenas de milhares de arquivos. O diretório é o ponto de montagem de uma partição LUKS ativa.

Eu queria renomear o diretório para:

/media/admin/my_data_on_60GB_partition

Eu não percebi na época, mas emiti o comando do diretório inicial e acabei fazendo:

~% sudo mv /media/admin/my_data my_data_on_60GB_partition

Então o mvprograma começou a se mover /media/admin/my_datae seu conteúdo para um novo diretório ~/my_data_on_60GB_partition.

Eu usei Ctrl+ Cpara cancelar o comando no meio, então agora eu tenho um monte de arquivos divididos em diretórios:

~/my_data_on_60GB_partition    <---  about 2GB worth files in here

e

/media/admin/my_data           <---- about 47GB of orig files in here    

O novo diretório ~/my_data_on_60GB_partitione alguns de seus subdiretórios são de propriedade da raiz.
Estou assumindo que o mvprograma deve ter copiado os arquivos como root inicialmente e, depois da transferência chown, os voltou para a minha conta de usuário.

Eu tenho um backup um pouco antigo do diretório / partição.
Minha pergunta é: é possível restaurar com segurança o grupo de arquivos que foram movidos?

Ou seja, posso apenas executar:

sudo mv ~/my_data_on_60GB_partition/*  /media/admin/my_data

ou devo desistir de tentar recuperar, pois os arquivos estão possivelmente corrompidos e parcialmente completos, etc.?

  • OS - Ubuntu 16.04
mv --version  
mv (GNU coreutils) 8.25
the_velour_fog
fonte
36
Adquira o hábito ao entrar em pânico para digitar Control-Z(pausar) em vez de Control-C. Nesse caso, você seria capaz de ver qual arquivo estava sendo transferido naquele momento e, assim, saber qual arquivo foi copiado apenas parcialmente. Você pode então decidir com calma como proceder. (Use kill -stoppara processos que não estão no tty).
meuh 27/10/16
11
2GB + 47GB = 60GB ???
tbodt
7
@tbodt (2GB + 47GB) < 60GB. a capacidade da partição é de 60 GB, tamanho da pasta e seu conteúdo: 49 GB.
the_velour_fog

Respostas:

87

Ao mover arquivos entre sistemas de arquivos, mvnão exclui um arquivo antes de terminar de copiá-lo e processa os arquivos sequencialmente (eu disse inicialmente que ele copia e exclui cada arquivo por vez, mas isso não é garantido - pelo menos as mvcópias GNU excluem cada comando - argumento de linha, por sua vez, e POSIX especifica esse comportamento ). Portanto, você deve ter no máximo um arquivo incompleto no diretório de destino e o original ainda estará no diretório de origem.

Para mover as coisas de volta, adicione a -isinalização para mvnão substituir nada:

sudo mv -i ~/my_data_on_60GB_partition/* /media/admin/my_data/

(supondo que você não tenha nenhum arquivo oculto do qual restaurar ~/my_data_on_60GB_partition/), ou melhor ainda (como você descobriu que você pode ter muitos arquivos esperando para serem excluídos), adicione o -nsinalizador para mvque não substitua nada, mas que não substitua pergunte sobre isso:

sudo mv -n ~/my_data_on_60GB_partition/* /media/admin/my_data/

Você também pode adicionar a -vbandeira para ver o que está sendo feito.

Com qualquer POSIX compatível mv, a estrutura de diretórios original ainda deve estar intacta; portanto, você pode verificar isso - e simplesmente excluir /media/admin/my_data... (No caso geral, acho que a mv -nvariante é a abordagem segura - ele lida com todas as formas de mv, incluindo, por exemplo mv /media/admin/my_data/* my_data_on_60GB_partition/ .)

Você provavelmente precisará restaurar algumas permissões; você pode fazer isso em massa usando chowne chmod, ou restaurá-los a partir de backups usando getfacle setfacl(obrigado a Sato Katsura pelo lembrete ).

Stephen Kitt
fonte
Obrigado Stephen Kitt, isso é uma grande ajuda! Eu posso usar findpara encontrar e definir permissões. Existem muitos arquivos no novo diretório que possuem espaços nos nomes de arquivos, mas nenhum arquivo oculto - que eu conheço. Você acha que o globo no comando sudo mv -i ~/my_data_on_60GB_partition/* /media/admin/my_data/expandiria o nome do arquivo sem problemas de divisão de palavras? Eu estava pensando alternativamente que eu poderia usar o sudo rsync ~/my_data_on_60GB_partition/ /media/admin/my_data/que acredito que iria lidar com os caminhos de arquivo com espaços?
the_velour_fog
6
Só para ter certeza, quando coisas como o OP descrito acontecem, eu uso esse rsyncrecurso para verificar a integridade de todos os arquivos. Mas é bom saber que eu não preciso disso.
Hauleth 27/10/16
11
@the_velour_fog globbing lida com espaços nos nomes de arquivos sem problemas.
Stephen Kitt
5
Eu su command mv -i ...(ou su /bin/mv -i ...), em vez de sudo mv -i ...), no caso de algum administrador (estranho) tornar o "mv" uma função que faz o "mv -f" no nível do sistema (ou seja, / etc / profile ou esses arquivos gerais do sistema) .. comando command: inicie o comando alguma coisa, e não uma função ou apelido com o mesmo nome. (por exemplo: um pode ser (muito!) azarado e ter um (muito, muito ruim!) function mv { /bin/mv -f -- "$@" }em um arquivo que é sempre originado e, em seguida, "rm -i something" não pede nada (e apenas protesta que "-i "arquivo não existe) ... [Eu tenho ver essas coisas ... tremer ]
Olivier Dulac
3
@OlivierDulac - um exemplo perfeito de por que é uma prática ruim usar aliases ou scripts com os mesmos nomes dos programas padrão.
Joe
19

Depois de obter a resposta de Stephen Kitt e discutir este comando como uma solução potencial:

sudo mv -i ~/my_data_on_60GB_partition/* /media/admin/my_data/

Decidi adiar a execução até entender o que estava acontecendo, esta resposta descreve o que descobri e acabei fazendo.

Estou usando o Gnu, mvque copia arquivos para o destino; somente se a operação de cópia for bem-sucedida, ele excluirá o original.
No entanto, eu queria confirmar se mvessa sequência é executada um arquivo por vez. Se isso fosse verdade, o conteúdo da pasta original seria dividido em duas partes, uma parte deslocada para o destino e a outra ainda na fonte. E, possivelmente, haveria um arquivo que foi interrompido durante a cópia, que seria comum entre os dois diretórios - e provavelmente teria um formato incorreto.

Para descobrir arquivos comuns entre os dois diretórios, executei:

~% sudo diff -r --report-identical-files my_data_on_60GB_partition/. /media/admin/mydata/. | grep identical | wc -l
14237

Este resultado sugeriu que havia 14.237 instâncias dos mesmos arquivos nos diretórios de origem e de destino, confirmei verificando os arquivos manualmente - sim, havia muitos dos mesmos arquivos nos dois diretórios. Isso sugere que somente após a mvcópia de grandes faixas de arquivos ele executa a exclusão dos arquivos de origem. Uma pesquisa rápida no infono mvcomando mostrou

Ele mvusa primeiro o mesmo código usado cp -apara copiar os diretórios e arquivos solicitados e, assumindo que a cópia foi bem-sucedida, remove os originais. Se a cópia falhar, a parte que foi copiada para a partição de destino será removida.

Não executei o comando, mas suspeito que se tentasse executar

sudo mv -i ~/my_data_on_60GB_partition/* /media/admin/my_data/

O -i prompt antes da substituição provavelmente teria disparado mais de 14.000 vezes.

Então, para descobrir quantos arquivos totais no diretório recém-criado:

~% sudo find my_data_on_60GB_partition/ -type f -a -print | wc -l                                                                    
14238

Portanto, se houvesse um total de 14238 arquivos regulares no novo diretório e 14237 tivessem originais idênticos na origem, isso significa que havia apenas um arquivo no novo diretório que não tinha um arquivo idêntico correspondente na origem. Para descobrir o que era esse arquivo, executei o rsync de volta na direção da fonte:

~% sudo rsync -av --dry-run my_data_on_60GB_partition/ /media/admin/my_data
sending incremental file list
./
Education_learning_reference/
Education_learning_reference/Business_Education/
Education_learning_reference/Business_Education/Business_education_media_files/
Education_learning_reference/Business_Education/Business_education_media_files/Jeff Hoffman - videos/
Education_learning_reference/Business_Education/Business_education_media_files/Jeff Hoffman - videos/Jeff and David F interview/
Education_learning_reference/Business_Education/Business_education_media_files/Jeff Hoffman - videos/Jeff and David F interview/018 business plans-identifying main KPIs.flv

sent 494,548 bytes  received 1,881 bytes  330,952.67 bytes/sec
total size is 1,900,548,824  speedup is 3,828.44 (DRY RUN)

Uma verificação rápida confirmou que este era o arquivo malformado, onde o arquivo existia na origem e no destino, arquivo de destino = 64MB, original = 100MB. Este arquivo e sua hierarquia de diretórios ainda pertenciam à raiz e ainda não tinham as permissões originais restauradas.

Então, em resumo:

  • todos os arquivos que mvnunca foram alcançados ainda estão de volta em seus locais originais (obviamente)
  • todos os arquivos que mvcopiaram completamente ainda tinham suas cópias originais no diretório de origem
  • o arquivo que foi copiado apenas parcialmente ainda tinha o original de volta no diretório de origem

Em outras palavras, todos os arquivos originais ainda estavam intactos e a solução nesse caso foi simplesmente excluir o novo diretório!

the_velour_fog
fonte
Uau ... Eu atualizei minha resposta, -nseria melhor no caso geral. Eu verifiquei o mvcódigo fonte, ele exclui a fonte, um argumento de cada vez.
Stephen Kitt
@StephenKitt ah nice. Eu queria saber quando mvé que a exclusão na fonte. Assim, o comando mv foo bar bazse moveria foopara baz/foo , em seguida, elimine o original foo, em seguida, mover barpara baz/bar..?
2841616
Sim está certo; de fato, é o que o POSIX especifica (basicamente, para que qualquer erro que afete qualquer argumento de origem deixe intacta toda a hierarquia de origem).
Stephen Kitt
Eu acho que você poderia ter usado o diff para encontrar o arquivo inacabado também.
StarWeaver 29/10/16
11
Você deve usar em cmpvez de diffcomparar arquivos binários. Além disso, sua discussão acima faz sentido apenas ao mover arquivos por diferentes sistemas de arquivos. Não há cópia envolvida ao mover arquivos dentro do mesmo sistema de arquivos.
Satō Katsura
4

Eu apenas pensei em comentar que algumas pessoas podem ficar tentadas a jogar 'xargs' na mistura para executar as coisas em paralelo. Isso me dá vontade e eu realmente gosto da solução rsync acima.

Quanto às coisas do sistema de arquivos sobre movimentação e cópia e quando exatamente o original é excluído, o VFS e o (s) sistema (s) de arquivos subjacente se coordenam para garantir a atomicidade por arquivo antes de chegar à etapa de exclusão. Portanto, mesmo que seja interrompido antes que o arquivo de destino seja totalmente gravado, todo o bloqueio no VFS é realmente rigoroso e protege contra coisas como intercalação aleatória de dados, mesmo em casos paralelos. (Eu trabalhei no Linux VFS e NFS4)

Adicionar 'xargs' à mistura provavelmente tornaria a etapa de verificação de sanidade dupla uma dor de cabeça, com vários arquivos no meio do trânsito. Eu gostaria de ter tido mais scripts de nível de sistema. Bons lembretes para mim!

Adorei a pergunta, bom para teias de aranha, e me faz amar rsync novamente. Felicidades!

david richter
fonte
11
Sem mencionar o problema quando os nomes de arquivos contêm espaços em branco.
Curinga