파이프의 출력을 복제할 수 있나요?

파이프의 출력을 복제할 수 있나요?

작업은 간단합니다. 내 스크립트의 일부는 md5 및 sha1 해시를 모두 계산해야 합니다. 입력은 파일(큰 파일)이며 나중에 출력 구성을 위해 해시를 MD 및 SH 변수에 넣어야 합니다.

처리된 파일은 정말 크지만(수백 GB) 일단 읽은 데이터를 여러 번 사용하려고 합니다. 나는 다음 방법으로 채택한 프로세스 대체라는 것을 발견했습니다.

$ dd if=big.tgz 2>/dev/null |tee >(sha1sum ) > >(md5sum ) ;

대신에:

$ SH=$(sha1sum big.tgz); MD=$(md5sum big.tgz);

하지만 다음을 찾았습니다.

  • 둘 다 대략적으로 걸리기 때문에 리소스도 시간 절약도 없는 것 같습니다. 40초(4.776GB 파일의 경우)

  • >(md5sum )나중에 스크립트에서 사용하기 위해 하위 프로세스의 결과를 변수 MD에 저장하는 방법을 모르겠습니다.

나는 Pipexec을 이해하려고 노력했지만 멋진 컬러 일러스트레이션도 아직까지는 성공하지 못했습니다.

VAR=$(command) 이외의 출력을 vriable로 리디렉션하는 다른 방법이 있습니까?

답변1

성능의 경우 CPU에 따라 제한될 수 있습니다. 실제로 MD5와 sha1sum 모두 40초 안에 4.7TB가 빠르게 느껴집니다. 그러니까 이렇게 일을 해도. 그만한 가치가 있는 만큼 디스크 IO가 줄어들 것입니다.

당신은 정말로 이것을 할 필요가 없습니다 dd. 나중에 사용하기 위해 sha1sum 및 md5sum의 출력을 파일에 직접 쓸 수도 있습니다.

tee < big.tgz  >(sha1sum > big.tgz.sha1 ) > >(md5sum > big.tgz.md5 )
sha1=`cat big.tgz.sha1`
md5=`cat big.tgz.md5`

AFAIK에는 두 변수를 서로 다른 값으로 동시에 설정할 수 있는 방법이 없기 때문에 이와 같은 임시 파일( big.tgz.sha1및 ) 을 사용하는 것이 좋습니다. big.tgz.md5하나를 변수로 직접 캡처할 수 있지만 둘 다를 캡처할 수는 없습니다. 그리고 동시에 동일한 stdout에 쓰기 md5sum와 쓰기를 허용하면 예측할 수 없는 문제가 발생할 수 있습니다.sha1sum

답변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

이론적으로 이는 디스크에서 데이터를 두 번 읽으므로 좋지 않습니다.

실제로 두 판독기를 병렬(및 백그라운드)로 실행하면 디스크 캐시가 이를 처리하여 데이터를 한 번만 읽을 수 있습니다. 이는 해시 계산이 빠르고 I/O가 느리기 때문에 어떤 프로세스도 다른 프로세스에서 벗어날 수 없다고 가정합니다.

(저는 이전에 다른 맥락에서 두 번 읽는 것에 대해 게시했습니다.md5sum과 함께 pv 사용- 일반적으로 작동하지만 일부 위험이 수반되므로 tee여전히 더 안정적인 방법입니다. )

답변3

parsetGNU 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]}

관련 정보