du fornece dois resultados diferentes para o mesmo arquivo


23

Sou estudante de química computacional com acesso a um cluster Linux. O cluster consiste em um servidor de arquivos muito grande (25 TB), ao qual várias dezenas de nós de computação estão conectados. Cada nó de computação consiste em 8 a 24 núcleos Intel Xeon. Cada nó de computação também contém um disco local de cerca de 365 TB.

Como o servidor de arquivos é acessado rotineiramente por uma dúzia de usuários no grupo de pesquisa, o servidor de arquivos é usado principalmente para armazenamento de arquivos a longo prazo (o backup é feito todas as noites, enquanto o backup dos discos locais dos nós de computação nunca é feito). Assim, o administrador do sistema nos instruiu a executar simulações nos discos locais - que têm E / S mais rápidas que o servidor de arquivos - para não diminuir a velocidade do servidor de arquivos para os outros usuários.

Portanto, executo simulações nos discos locais e, depois que elas terminam, copio os arquivos de trajetória - estou executando simulações de dinâmica molecular (MD) - no servidor de arquivos para armazenamento. Suponha que eu tenha um arquivo de trajetória chamado traj.trrem um diretório no disco local de um nó /home/myusername/mysimulation1/traj.trr,. Para armazenamento de longo prazo, eu sempre copio traj.trrpara um diretório no servidor de arquivos,, ~/mysimulation1/traj.trronde ~representa meu diretório no servidor de arquivos /export/home/myusername,. Depois de copiá-lo, costumo usar du -hpara verificar /home/myusername/mysimulation1/traj.trrse o mesmo tamanho de arquivo é ~/mysimulation1/traj.trr. Dessa forma, posso ter pelo menos razoavelmente certeza de que a transferência para o servidor de arquivos foi bem-sucedida. Por exemplo:

cd /home/myusername/mysimulation1/
cp -v traj.trr ~/mysimulation1/
du /home/myusername/mysimulation1/traj.trr -h
du ~/mysimulation1/traj.trr -h

Se as duas chamadas du -htiverem o mesmo tamanho de arquivo legível por humanos, posso ter certeza razoável de que a transferência / cópia foi bem-sucedida. (Meus traj.trrarquivos típicos variam em tamanho de 15 a 20 GB, dependendo da simulação exata que eu executei.) Se eu executar du(ou seja, sem a -hopção) nos dois traj.trrarquivos, seus tamanhos em bytes são geralmente muito, muito semelhantes - - geralmente dentro de apenas alguns bytes. Eu tenho usado esse método geral há um ano e meio, sem problemas.

No entanto, recentemente , encontrei o seguinte problema: às vezes,du -hinforma que os doistraj.trrarquivos são diferentes em tamanho por vários GB. Aqui está um exemplo:

cd /home/myusername/mysimulation1/            # this is the local disk
cp -v traj.trr ~/mysimulation1/
du traj.trr -h
cd ~/mysimulation1/                           # this is the fileserver
du traj.trr -h

A saída das duas chamadas para du -hé a seguinte, respectivamente:

20G     traj.trr
28G     traj.trr

Acredito que o primeiro (ou seja, o traj.trrdisco local /home/myusername/mysimulation1/) tenha o tamanho correto de arquivo, pois minhas trajetórias de simulação devem ter entre 15 e 20 GB cada. Mas então como o arquivo no servidor de arquivos pode ser realmente maior ? Eu podia ver como poderia ser menor, se de alguma forma a cptransferência falhou. Mas não vejo como poderia ser maior .

Recebo uma saída semelhante quando executo os mesmos comandos acima, mas sem a -hopção fornecida du:

20717480        traj.trr
28666688        traj.trr

Você consegue pensar em alguma razão para a diferença?

Se, por alguma chance improvável, duestiver de alguma forma com defeito, posso concordar com isso. Mas eu realmente preciso ter certeza de que a cópia do traj.trrservidor de arquivos esteja completa e idêntica à sua versão de origem no disco local. Preciso excluir o arquivo local para ter espaço em disco local suficiente para executar novas simulações, mas não posso me permitir que a versão do traj.trrservidor de arquivos seja corrompida.

O formato de arquivo .trr (do pacote de dinâmica molecular do Gromacs) é um formato binário, não texto. Portanto, não tenho certeza se os arquivos podem ser comparados com segurança por um programa como o diff.


5
Tente executar md5sumou sha1sumnos arquivos. Eles combinam?
Cjm

2
@cjm Acabei de executar md5sumos dois arquivos. As duas somas de verificação coincidem. Então eu acho que isso significa que os dois arquivos são iguais?
22413 Andrew

3
Quais tamanhos são relatados por ls -l? O comando durelata quanto espaço no disco é usado para o seu arquivo, e não o tamanho dele. O tamanho do disco pode ser influenciado pelo seu sistema de arquivos e suas estratégias de alocação.
casey

2
@casey ls -l -hdiz que os dois arquivos têm 20 GB. Da mesma forma, ls -ldiz que os dois arquivos são 21214683940 bytes. Acho que os arquivos têm o mesmo tamanho, mas não usam a mesma quantidade de espaço em disco (de acordo com du).
Andrew

2
@ Andrew, considerando os tamanhos informados por ls e os hashes iguais, você pode concluir que os arquivos são iguais. Essas ferramentas são o que lhe dá a confiança de que você precisa e mostram que du não é a ferramenta para atender às suas necessidades.
precisa

Respostas:


32

Você realmente deve usar algo como md5sumou sha1sumpara verificar a integridade.

Se você realmente deseja usar o tamanho, use ls -lou du -b.

O duutilitário normalmente mostra apenas o uso do disco no arquivo, ou seja, quanto do sistema de arquivos é usado por ele. Esse valor depende totalmente do sistema de arquivos de backup e de outros fatores, como arquivos esparsos.

Exemplo:

$ truncate -s 512M foo
$ cat foo >bar
$ ls -l foo bar
-rw-r--r-- 1 michas users 536870912 23. Dez 00:06 bar
-rw-r--r-- 1 michas users 536870912 23. Dez 00:03 foo
$ du foo bar
0       foo
524288  bar
$ du -b foo bar
536870912       foo
536870912       bar

Temos dois arquivos, ambos contendo 512 MB de zeros. O primeiro é armazenado esparsamente e não utiliza espaço em disco, enquanto o segundo armazena cada byte explicitamente no disco. - Mesmo arquivo, mas uso de disco completamente diferente.

A -bopção pode ser boa para você:

   -b, --bytes
          equivalent to '--apparent-size --block-size=1'

   --apparent-size
          print apparent sizes, rather than disk usage; although the apparent
          size is  usually  smaller,  it  may  be  larger  due  to  holes  in
          ('sparse')  files, internal fragmentation, indirect blocks, and the
          like

8

Esse é um problema comum quando você coloca os mesmos dados em 2 HDs diferentes. Você desejará executar o ducomando com uma opção adicional, assumindo que ela possui - o que deve ser dado como esses nós do Linux.

O interruptor?

   --apparent-size
          print  apparent  sizes,  rather  than  disk  usage;  although the 
          apparent size is usually smaller, it may be larger due to holes in
          ('sparse') files, internal fragmentation, indirect blocks, and the 
          like

Exemplo

$ du -sh --apparent-size /home/sam/scsconfig.log ~/scsconfig.log 
93K /home/sam/scsconfig.log
93K /root/scsconfig.log

Os sistemas de arquivos acima são um disco local ( /root) enquanto o outro /home/samé um compartilhamento NFS do meu NAS.

$ df -h . /home/sam
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup00-LogVol00
                      222G  118G   92G  57% /
mulder:/export/raid1/home/sam
                      917G  566G  305G  65% /home/sam

Então, como vai?

Isso confunde muitas pessoas, mas lembre-se de que, quando os arquivos são armazenados em um disco, eles consomem blocos de espaço, mesmo que estejam usando apenas uma parte desses blocos. Quando você executa dusem o --apparent-sizetamanho do bloco, utiliza o tamanho do espaço em disco usado, não o espaço real consumido pelo (s) arquivo (s).

usando uma soma de verificação?

Essa é provavelmente uma opção melhor se você estiver preocupado em comparar duas árvores de arquivos. Você pode usar este comando para calcular uma soma de verificação para todos os arquivos e, em seguida, calcular uma soma de verificação final de somas de verificação. Este exemplo usa, sha1summas você pode usar com a mesma facilidade md5sum.

$ cd /some/dir
$ find . -type f \( -exec sha1sum "{}" \; \) | sort -k2,2 | sha1sum

Exemplo

$ cd ~/dir1
$ find . -type f \( -exec sha1sum "{}" \; \) | sort -k2,2 | sha1sum
55e2672f8d6fccff6d83f0bffba1b67aeab87911  -

$ cd ~/dir2
$ find . -type f \( -exec sha1sum "{}" \; \) | sort -k2,2 | sha1sum
55e2672f8d6fccff6d83f0bffba1b67aeab87911  -

Então podemos ver que as 2 árvores são idênticas.

(Nota: o comando find listará os arquivos como eles apareceram no sistema de arquivos. Portanto, se você estiver comparando dois diretórios de um sistema de arquivos diferente (por exemplo, Ext3 vs. APFS), será necessário classificar primeiro antes do sha1sum final. (Adicionado por Xianjun Dong)


5

A resposta curta: não teste o tamanho do arquivo, teste o status de retorno do comando. O status de retorno é a única indicação confiável de que a cópia foi bem-sucedida (além de comparar os dois arquivos byte a byte, diretamente ou indiretamente - o que é redundante se a cópia for bem-sucedida).

Verificar o tamanho do arquivo não é uma maneira muito útil de verificar se uma cópia foi bem-sucedida. Em alguns casos, pode ser uma verificação de integridade útil, por exemplo, quando você baixa um arquivo da Web. Mas aqui há uma maneira melhor.

Todos os comandos do Unix retornam um status para indicar se foram bem-sucedidos: 0 para êxito, 1 ou mais para erros. Portanto, verifique o status de saída de cp. cpnormalmente, uma mensagem de erro será impressa se ela falhar, indicando qual é o erro. Em um script, o status de saída do último comando está na variável mágica $?.

cp -v traj.trr ~/mysimulation1/
if [ $? -ne 0 ]; then
  echo 1>&2 "cp failed due to the error above"
  exit 2
 fi

Em vez de verificar se $?é zero, você pode usar operadores booleanos.

cp -v traj.trr ~/mysimulation1/ || exit 2

Se você estiver executando um script e desejar que o script pare se algum comando falhar, execute set -e. Se algum comando falhar (ou seja, retornar um status diferente de zero), o script sairá imediatamente com o mesmo status que o comando.

set -e
…
cp -v traj.trr ~/mysimulation1/

Quanto ao motivo pelo qual seu arquivo copiado era maior, deve ser porque era um arquivo esparso . O arquivo esparso é uma forma bruta de compactação, onde blocos contendo apenas bytes nulos não são armazenados. Quando você copia um arquivo, o cpcomando lê e grava bytes nulos; portanto, onde o original tinha blocos ausentes, a cópia possui blocos cheios de bytes nulos. No Linux, o cpcomando tenta detectar arquivos esparsos, mas nem sempre é bem-sucedido; cp --sparse=alwaystorna mais difícil às custas de um aumento muito leve no tempo da CPU.

De maneira mais geral, dupoderia retornar resultados diferentes devido a outras formas de compactação. Sistemas de arquivos compactados são raros, no entanto. Se você deseja saber o tamanho de um arquivo como o número de bytes no arquivo, em oposição ao número de blocos de disco que ele usa, use em ls -lvez de du.


Muito obrigado! Você sabe se existe um utilitário (separado) que pode me dizer se meu arquivo é escasso ou não?
Andrew

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.