Posso duplicar a saída de um pipe?

Posso duplicar a saída de um pipe?

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 dddisso. 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.sha1e 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 md5sume sha1sumgravem 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 teeainda é o método mais confiável. )

Responder3

parsetdo GNU Parallel é feito para definir variáveis ​​em paralelo e --teefornecerá 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]}

informação relacionada