A adição da soma SHA1 (que garante matematicamente um grau ridiculamente alto de certeza de que os arquivos coincidem quando os hashes coincidem e os hashes não correspondem quando os arquivos não correspondem) adiciona uma medida de integridade de dados para proteger nos casos em que o subsistema de disco pode ter cometido um erro (silencioso) durante a gravação. Corrupção silenciosa é rara, mas insidiosa quando acontece.
Naturalmente, você ainda pode ter resultados confusos se tiver erros aleatórios durante a leitura, mas, nesse caso, as somas não corresponderão de qualquer maneira, a um grau extremamente alto de certeza. Em outras palavras, se o sistema estiver corrompido (RAM ou o disco produzindo bits errados / bits invertidos / dados corrompidos), isso falhará onde um simples &&
poderá ser bem-sucedido e as chances de isso chegar ao rm
A linha com dados corrompidos é vanishingly pequena (porque a maioria dos erros tende a corromper os dados de maneira aleatória, as chances de uma alteração aleatória causar uma colisão de hash no SHA1 durante a leitura são incrivelmente pequenas).
#!/bin/bash
set -e
set -o pipefail
ORIGSUM=$(gzip -dc file.gz | tee >(xz > file.xz) | sha1sum)
NEWSUM=$(unxz -c file.xz | sha1sum)
if [ "${ORIGSUM}" = "${NEWSUM}" ]; then rm file.gz; fi
O set -e
faz o script sair assim que qualquer linha do script retorna um código de saída diferente de zero.
Em seguida, usamos o comando tee
para copiar a saída não compactada do arquivo para ambos o xz
compressor, e para o programa sha1sum
. sha1sum
calcula a soma SHA1 dos dados originais contidos no arquivo compactado com gzip, descompactando-o temporariamente no programa sha1sum, que lê os dados para calcular a soma e, em seguida, descarta os dados. Ao usar tee
, nós só temos que pagar o custo da CPU para descompactar o arquivo uma vez.
Em seguida, executamos uma etapa adicional dispendiosa em termos computacionais (para super-extra-verificação) e removemos a compactação xz no arquivo (temporariamente, em um fluxo) e canalizamos para o sha1sum, para obter nosso "novo arquivo" SHA1 soma.
Em seguida, comparamos as duas somas e, se elas não forem iguais, ou se uma ou ambas forem de tamanho zero, obteremos um erro de script (que sai, graças a set -e
) ou o arquivo não será removido. Você pode implementar uma cláusula else
para tratamento de erros fácil de usar, se desejar, mas este script essencial como está será extremamente seguro, embora não seja muito informativo para um usuário executando o comando de forma interativa.
No final, o file.gz
só será desvinculado se e somente se o conteúdo não compactado de file.gz
e file.xz
forem exatamente idênticos no momento em que os hashes foram computados , com um grau astronomicamente alto de certeza (as chances de algo ruim dar errado seria algo como 1 em 1 com 300 zeros depois disso). Nesse ponto, você só precisa se preocupar com os dados sendo corrompidos após esse script sair. ;)
Desempenho
Este script será executado quase na mesma velocidade do seu script original na pergunta, exceto para a parte que executa unxz
. Felizmente, descomprimir a partir do LZMA é extremamente rápido, quase tão rápido quanto o Zip normal, e algo como uma ordem de grandeza mais rápida do que a compressão do para o LZMA. Se você tem uma CPU rápida e os arquivos são suficientemente pequenos, isso não deve adicionar muito tempo de execução ao script, mas se você valoriza a integridade dos dados em relação ao desempenho, é uma vitória clara.
Crédito em que o crédito é devido
Esta resposta no StackOverflow me ajudou substancialmente ao escrever este script.