Por que há uma enorme discrepância entre os tamanhos de arquivo relatados por du versus ls?

1

Em um servidor, eu tenho um diretório /opt/kafka/data/topics .

$ du -hs /opt/kafka/data/topics
52M     /opt/kafka/data/topics

Quando eu tar esse diretório como

$ tar czfv /tmp/topics.tar.gz /opt/kafka/data/topics

Eu recebo um tamanho de arquivo que faz sentido

$ ls -alh /tmp/topics.tar.gz
-rw-r--r-- 1 user user  11M Jan 12 15:15 kafka

No entanto, quando transfiro topics.tar.gz para o meu computador OS X local e o extraio, ocupa 10 GB!

Ao examinar mais de perto o conteúdo de /opt/kafka/data/topics no servidor, notei que, de acordo com ls , ele contém muitos arquivos de 10 MB:

$ find /opt/kafka/data -type f -exec ls -alh {} \;
... [output]
-rw-r--r-- 1 user user 10M Jan 12 02:45 /opt/kafka/data/topics/user-entities-KTABLE-REDUCE-STATE-STORE-0000000178-changelog-1/00000000000000000000.index
-rw-r--r-- 1 user user 10M Jan 12 02:45 /opt/kafka/data/topics/user-entities-KSTREAM-KEY-SELECT-0000000123-repartition-2/00000000000000000012.index
... [and many more]

du informa que cada um desses arquivos de 10 MB é de 0 bytes:

$ du -h /opt/kafka/data/topics/user-entities-KTABLE-REDUCE-STATE-STORE-0000000178-changelog-1/00000000000000000000.index
0       /opt/kafka/data/topics/user-entities-KTABLE-REDUCE-STATE-STORE-0000000178-changelog-1/00000000000000000000.index

Então, o que está acontecendo? Obviamente, estou sentindo falta de algo aqui:

  • du relata 52 milhões no total. Isso faz sentido porque o dispositivo em que /opt/kafka/data está montado é de apenas 5 GBs, df relata que está apenas 2% cheio e que tudo ainda está funcionando.
  • tar gzips o conteúdo para 10M. Isso também faz sentido.
  • ls informa que muitos dos arquivos têm 10M em disco e quando eu extraio o arquivo, recebo 10GB.
  • du informa que cada um desses mesmos arquivos tem 0 bytes.
  • mount informa que /dev/sdc on /opt/kafka/data type ext4 (rw,relatime,data=ordered)

Nada acrescenta. Existe algum tipo de compressão em disco transparente que não conheço?

    
por Dmitry Minkovsky 12.01.2018 / 17:28

1 resposta

2

Com base na discussão nos comentários, todos os arquivos são esparsos. Esse tipo de coisa realmente confunde muitas pessoas na primeira vez que elas lidam com isso, então não se sinta mal.

O que está acontecendo aqui com os valores reportados por ls e du ?

Isso é mais facilmente explicado com um exemplo.

Digamos que você crie um arquivo vazio e, em seguida, escreva 1 MB de dados, começando logo no início. O arquivo resultante terá 1 MB de tamanho e ocupará 1 MB no disco. Tanto ls quanto du reportarão o mesmo tamanho de 1 MB para o arquivo.

Agora, em vez disso, você cria um arquivo vazio e, em seguida, chama seek() para mover 1 MB para o arquivo e, em seguida, escreve um byte. O arquivo resultante parecerá ter 1 MB + 1 byte, mas há apenas 1 byte de dados nele.

Em sistemas de arquivos mais antigos, o segundo arquivo levaria muito tempo para escrever esse byte de 1 dado, porque o SO estaria ocupado escrevendo 1 MB de bytes nulos antes de escrever o último byte de dados reais. / p>

Essa ineficiência (em termos de tempo para criar o arquivo e espaço usado no disco) é onde entram os arquivos esparsos. Em vez de escrever 1 MB de bytes nulos, um SO que suporte arquivos esparsos (como todos os UNIX modernos) sistemas) anotará nos metadados do sistema de arquivos que a forma da região 0-1MB está vazia e, em seguida, armazena apenas o único byte que você escreveu. Como resultado, o arquivo parecerá ter 1 MB + 1 byte, mas no disco ele ocupará apenas 1 byte. Além disso, quando algo vai ler esse arquivo, todas as regiões que o sistema operacional anotou como vazias serão lidas apenas como bytes nulos (para que não pareça diferente dos programas do usuário do primeiro arquivo).

É aí que a discrepância entre os valores reportados por ls e du vem. Por padrão, ls informa o tamanho aparente dos arquivos (isto é, quantos dados você leria se você começasse a ler o arquivo no primeiro byte e lesse todo o caminho até o final), enquanto du informaria o espaço real usado no disco pelo arquivo (geralmente não incluindo outros truques de economia de espaço feitos pelo SO como compactação transparente). du concorda com df neste caso porque df apenas informa a quantidade de espaço que está sendo fisicamente usado no disco.

Ao alterar o comando ls -l para ls -ls , você receberá uma coluna extra mostrando o tamanho real do disco para os arquivos, o que deve concordar com du .

    
por 12.01.2018 / 18:11