Могу ли я дублировать вывод канала?

Могу ли я дублировать вывод канала?

Ну, задача проста: часть моего скрипта должна вычислять хеши 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]}

Связанный контент