Ну, задача проста: часть моего скрипта должна вычислять хеши md5 и sha1. Входные данные — это файл, большой файл, а хеши должны быть помещены в переменные MD и SH для последующей компоновки выходных данных.
Хотя обработанные файлы действительно большие (сотни ГБ), я пытаюсь использовать некое многократное использование данных после прочтения. Я нашел нечто, называемое заменой процессов, что я адаптировал следующим образом:
$ dd if=big.tgz 2>/dev/null |tee >(sha1sum ) > >(md5sum ) ;
вместо:
$ SH=$(sha1sum big.tgz); MD=$(md5sum big.tgz);
Но я нашел следующее:
по-видимому, нет ни экономии ресурсов, ни экономии времени, поскольку и то, и другое занимает около 40 с (для файла размером 4,776 ГБ)
Я понятия не имею, как сохранить результат подпроцесса
>(md5sum )
в переменную MD, чтобы использовать его позже в скрипте.
Я пытался понять pipexec, но даже прекрасные цветные иллюстрации пока не дали результата.
Есть ли другой способ перенаправить вывод в переменную, кроме VAR=$(command)?
решение1
Что касается производительности, вы можете быть ограничены процессором. На самом деле 4,7 ТБ за 40 секунд для MD5 и sha1sum кажутся быстрыми. Так что даже если вы работаете таким образом. Если это того стоит, вы сократите дисковый ввод-вывод.
Вам действительно не нужно dd
это делать. Вы также можете просто записать вывод sha1sum и md5sum прямо в файл для дальнейшего использования
tee < big.tgz >(sha1sum > big.tgz.sha1 ) > >(md5sum > big.tgz.md5 )
sha1=`cat big.tgz.sha1`
md5=`cat big.tgz.md5`
Я предлагаю использовать временные файлы, такие как этот ( big.tgz.sha1
и big.tgz.md5
), потому что, насколько мне известно, нет способа одновременно задать две переменные с разными значениями. Вы можете захватить одну из них напрямую в переменную, но не обе. И разрешение md5sum
и sha1sum
писать в один и тот же stdout одновременно может вызвать непредсказуемые проблемы.
решение2
Ну, вы можете просто добавить еще одно перенаправление внутрь:
tee < big.tgz >(sha1sum > big.tgz.sha1sum) >(md5sum > big.tgz.md5sum)
Вы также можете использовать вывод как есть, учитывая, что sha1 и md5 легко различить (разная длина, поэтому не возникает путаницы, что есть что).
Существуют также утилиты, которые самостоятельно вычисляют несколько контрольных сумм, не прибегая к сложным операциям с tee
.
На самом деле вышесказанное можно записать и без tee
:
sha1sum big.tgz > big.tgz.sha1sum &
md5sum big.tgz > big.tgz.md5sum
wait # for sha1sum
Теоретически это плохо, так как данные считываются с диска дважды.
На практике, запуск обоих считывателей параллельно (и в фоновом режиме) должен позволить дисковому кэшу справиться с этим, так что данные фактически будут считываться только один раз. Это предполагает, что вычисление хэша происходит быстро, а ввод-вывод — медленно, поэтому ни один процесс не может оторваться от другого.
(Ранее я писал о чтении дважды в другом контексте здесь:Использование pv с md5sum- хотя обычно это работает, есть некоторые риски, поэтому tee
это все равно более надежный метод.)
решение3
parset
из GNU Parallel создан для параллельной установки переменных и --tee
направляет входные данные нескольким командам:
parset md5,sha1,sha256 --pipe --tee {} ::: md5sum sha1sum sha256sum < bigfile
echo $sha1
parset sumarr --pipe --tee {} ::: md5sum sha1sum sha256sum < bigfile
echo ${sumarr[1]}