Bueno, la tarea es simple: una parte de mi script tiene que calcular hashes md5 y sha1. La entrada es un archivo (un archivo grande) y los hashes deben colocarse en las variables MD y SH para su posterior composición de salida.
Si bien los archivos procesados son realmente grandes (cientos de GB), intento utilizar algún tipo de uso múltiple de los datos una vez leídos. Encontré algo llamado sustitución de procesos que adopté de la siguiente manera:
$ dd if=big.tgz 2>/dev/null |tee >(sha1sum ) > >(md5sum ) ;
en lugar de:
$ SH=$(sha1sum big.tgz); MD=$(md5sum big.tgz);
Pero encontré lo siguiente:
aparentemente no hay ahorro de recursos ni de tiempo ya que ambos llevan aprox. 40s (para archivos de 4,776 GB)
No tengo idea de cómo guardar el resultado del subproceso
>(md5sum )
en la variable MD para usarlo más adelante en el script.
Intenté entender el pipexec pero ni siquiera las bonitas ilustraciones en color tuvieron éxito hasta el momento.
¿Existe alguna otra forma de redirigir la salida a una variable, además de VAR=$(command)?
Respuesta1
En cuanto al rendimiento, es posible que esté limitado por la CPU. En realidad, 4,7 TB en 40 segundos tanto para MD5 como para sha1sum parecen rápidos. Incluso si trabajas de esta manera. Por si sirve de algo, habrá reducido la E/S del disco.
Realmente no es necesario dd
para esto. También puede simplemente escribir la salida de sha1sum y md5sum directamente en un archivo para su uso posterior.
tee < big.tgz >(sha1sum > big.tgz.sha1 ) > >(md5sum > big.tgz.md5 )
sha1=`cat big.tgz.sha1`
md5=`cat big.tgz.md5`
Sugiero usar archivos temporales como este ( big.tgz.sha1
y big.tgz.md5
) porque AFAIK no hay forma de configurar simultáneamente dos variables con valores diferentes. Puede capturar uno directamente en una variable, pero no ambos. Y permitir que ambos md5sum
escriban sha1sum
en la misma salida estándar al mismo tiempo podría causar problemas impredecibles.
Respuesta2
Bueno, puedes agregar otra redirección dentro:
tee < big.tgz >(sha1sum > big.tgz.sha1sum) >(md5sum > big.tgz.md5sum)
También puede tomar el resultado tal como está, considerando que es fácil diferenciar entre sha1 y md5 (longitud diferente para que no haya confusión sobre cuál es cuál).
También hay utilidades que calculan múltiples sumas de verificación por sí solas, sin pasar por obstáculos tee
.
En realidad, lo anterior también se puede escribir sin tee
:
sha1sum big.tgz > big.tgz.sha1sum &
md5sum big.tgz > big.tgz.md5sum
wait # for sha1sum
En teoría, esto es malo ya que los datos se leen del disco dos veces.
En la práctica, ejecutar ambos lectores en paralelo (y en segundo plano) debería permitir que la caché del disco lo maneje de modo que los datos se lean efectivamente solo una vez. Esto supone que el cálculo hash es rápido y la E/S es lenta, por lo que ningún proceso puede escapar del otro.
(Anteriormente publiqué sobre leer dos veces en otro contexto aquí:Usando pv con md5sum- Aunque normalmente funciona, conlleva algunos riesgos, por lo que tee
sigue siendo el método más fiable. )
Respuesta3
parset
de GNU Parallel está diseñado para configurar variables en paralelo y --tee
conectará la entrada a múltiples comandos:
parset md5,sha1,sha256 --pipe --tee {} ::: md5sum sha1sum sha256sum < bigfile
echo $sha1
parset sumarr --pipe --tee {} ::: md5sum sha1sum sha256sum < bigfile
echo ${sumarr[1]}