Bem, a tarefa é simples: uma parte do meu script precisa calcular os hashes md5 e sha1. A entrada é um arquivo - arquivo grande - e os hashes devem ser colocados nas variáveis MD e SH para posterior composição da saída.
Embora os arquivos processados sejam muito grandes (centenas de GB), tento usar algum tipo de uso múltiplo de dados depois de lidos. Encontrei algo chamado substituição de processo que adotei da seguinte maneira:
$ dd if=big.tgz 2>/dev/null |tee >(sha1sum ) > >(md5sum ) ;
em vez de:
$ SH=$(sha1sum big.tgz); MD=$(md5sum big.tgz);
Mas encontrei o seguinte:
aparentemente não há recursos nem economia de tempo, pois ambos levam aprox. 40s (para arquivo de 4,776 GB)
Não tenho ideia de como salvar o resultado do subprocesso
>(md5sum )
na variável MD para usar posteriormente no script
Tentei entender o pipexec, mas mesmo as belas ilustrações coloridas não tiveram sucesso até agora.
Existe alguma outra maneira de redirecionar a saída para um vriável, diferente de VAR=$(command) ?
Responder1
Quando se trata de desempenho, você pode estar limitado pela CPU. Na verdade, 4,7 TB em 40 segundos para MD5 e sha1sum parecem rápidos. Então, mesmo se você trabalhar dessa maneira. Pelo que vale a pena, você terá IO de disco reduzido.
Você realmente não precisa dd
disso. Você também pode simplesmente escrever a saída de sha1sum e md5sum diretamente em um arquivo para uso posterior
tee < big.tgz >(sha1sum > big.tgz.sha1 ) > >(md5sum > big.tgz.md5 )
sha1=`cat big.tgz.sha1`
md5=`cat big.tgz.md5`
Estou sugerindo o uso de arquivos temporários como este ( big.tgz.sha1
e big.tgz.md5
) porque no AFAIK não há como definir simultaneamente duas variáveis com valores diferentes. Você pode capturar um diretamente em uma variável, mas não ambos. E permitir que ambos md5sum
e sha1sum
gravem no mesmo stdout ao mesmo tempo pode causar problemas imprevisíveis.
Responder2
Bem, você pode simplesmente adicionar outro redirecionamento dentro:
tee < big.tgz >(sha1sum > big.tgz.sha1sum) >(md5sum > big.tgz.md5sum)
Você também pode considerar a saída como está, considerando que é fácil diferenciar entre sha1 e md5 (comprimento diferente para que não haja confusão sobre qual é qual).
Existem também utilitários que calculam várias somas de verificação por conta própria, sem se preocupar com o tee
.
Na verdade, o acima também pode ser escrito sem tee
:
sha1sum big.tgz > big.tgz.sha1sum &
md5sum big.tgz > big.tgz.md5sum
wait # for sha1sum
Em teoria, isso é ruim porque os dados estão sendo lidos do disco duas vezes.
Na prática, a execução de ambos os leitores em paralelo (e em segundo plano) deve permitir que o cache do disco manipule isso para que os dados sejam efetivamente lidos apenas uma vez. Isso pressupõe que o cálculo do hash seja rápido e a E/S seja lenta, de modo que nenhum processo possa fugir do outro.
(Eu postei anteriormente sobre a leitura duas vezes em outro contexto aqui:Usando pv com md5sum- embora geralmente funcione, existem alguns riscos envolvidos, por isso tee
ainda é o método mais confiável. )
Responder3
parset
do GNU Parallel é feito para definir variáveis em paralelo e --tee
fornecerá a entrada para vários comandos:
parset md5,sha1,sha256 --pipe --tee {} ::: md5sum sha1sum sha256sum < bigfile
echo $sha1
parset sumarr --pipe --tee {} ::: md5sum sha1sum sha256sum < bigfile
echo ${sumarr[1]}