하드웨어 리소스로 넘치지 않는 즉각적인 스트림 압축?


23

200GB의 사용 가능한 디스크 공간, 16GB의 RAM (데스크톱 및 커널이 ~ 1GB를 점유) 및 6GB의 스왑이 있습니다.

240GB 외부 SSD가 있으며 70GB는 1을 사용 하고 나머지는 무료로 사용 하므로 디스크에 백업해야합니다.

일반적으로 dd if=/dev/sdb of=Desktop/disk.img디스크를 먼저 압축 한 다음 압축하지만 이미지를 먼저 만드는 것은 옵션이 아닙니다. 압축 단계로 인해 여유 공간이 찌그러 지더라도 디스크 공간이 훨씬 많이 필요하므로 최종 아카이브는 디스크에 쉽게 맞출 수 있습니다.

dd기본적으로 STDOUT에 쓰고 gzipSTDIN에서 읽을 수 있으므로 이론적으로 쓸 수 dd if=/dev/sdb | gzip -9 -는 있지만 gzip바이트를 읽는 데 비해 바이트를 읽는 데 훨씬 오래 걸립니다 dd.

보낸 사람 man pipe:

파이프의 쓰기 엔드에 기록 된 데이터는 파이프의 읽기 엔드에서 읽을 때까지 커널에 의해 버퍼링됩니다.

필자 |는 실제 파이프와 같은 것으로 시각화합니다. 하나는 데이터를 입력하고 다른 하나는 파이프 대기열에서 데이터를 가능한 빨리 가져옵니다.

왼쪽의 프로그램이 파이프의 다른 쪽에서 처리 할 수있는 것보다 더 많은 데이터를 더 빨리 쓰면 어떻게됩니까? 메모리가 많이 걸리거나 스왑 사용이 발생합니까? 아니면 커널이 디스크에 FIFO를 작성하여 디스크를 채우려 고합니까? 아니면 SIGPIPE Broken pipe버퍼가 너무 크면 실패 합니까?

기본적으로 이것은 두 가지 질문으로 요약됩니다.

  1. 한 번에 읽는 것보다 더 많은 데이터를 파이프에 입력하면 어떤 영향을 미칩니 까?
  2. 압축되지 않은 전체 데이터 스트림을 디스크에 넣지 않고 데이터 스트림을 디스크로 압축하는 안정적인 방법은 무엇입니까?

참고 1 : 사용 된 처음 70GB를 정확하게 복사 할 수 없으며 조각화 및 전체 내용을 그대로 유지 해야하는 기타 요소로 인해 작동중인 시스템 또는 파일 시스템을 얻을 것으로 예상됩니다.


왜 사용자 디렉토리와 설치된 비표준 소프트웨어 목록 대신 전체 파일 시스템을 백업해야합니까?
jamesqf 2016 년

5
@jamesqf 예 : 복구가 훨씬 쉬우므로 ...
deviantfan

4
@jamesqf 부트 섹터와 스왑 파티션도 있으므로 10 억 개의 성가신 파일 대신 디스크를 정확하게 다시 만들 수 있습니다.
고양이

3
임의 팁 :로보기 lzop대신 gzip; 압축 비율이 약간 낮아서 훨씬 빠르게 압축됩니다. 압축 속도가 실제 병목 현상이 발생할 수있는 디스크 이미지에 이상적입니다.
marcelm

1
"왼쪽의 프로그램이 파이프의 다른 쪽에서 처리 할 수있는 것보다 더 많은 데이터를 더 빨리 쓰면 어떻게 될까요?" 커널은 파이프에 공간이 더 확보 될 때까지 쓰기 프로세스를 휴면 상태로 만듭니다.
Tavian Barnes 2012

답변:


16

기술적으로 당신은 필요하지 않습니다 dd:

gzip < /dev/drive > drive.img.gz

당신이 사용을 할 경우 dd, 당신은 항상 같은 기본 블록 크기보다 큰 함께 이동해야 dd bs=1M하거나 콜 지옥 고통 ( dd그 이후의 기본 블록 크기는 512 바이트 read()S와 write()이다의 4096당 콜을 MiB너무 많이 오버 헤드).

gzip -9CPU를 거의 사용하지 않고 더 많은 CPU를 사용합니다. 경우 gzip당신을 아래로 둔화되고, 압축 수준을 낮추거나 다른 (빠른) 압축 방법을 사용합니다.

dd이미지 대신 파일 기반 백업을 수행하는 경우 전혀 압축할지 여부를 결정하는 논리가있을 수 있습니다 (다양한 파일 유형에 대해서는 압축 할 필요가 없습니다). dar( tar대안`)은 그렇게 할 수있는 옵션이있는 예입니다.

여유 공간이 ZERO 인 경우 (트림 후 안정적으로 0을 반환 fstrim하고 캐시를 삭제하고 삭제 한 SSD이기 때문에 ) 플래그 dd와 함께 conv=sparse사용하여 제로 영역에 제로 디스크 공간을 사용하는 압축되지 않은 루프 마운트 가능 스파 스 이미지를 만들 수 있습니다. . 스파 스 파일을 지원하는 파일 시스템에서 이미지 파일을 백업해야합니다.

또는 일부 파일 시스템의 경우 사용 된 영역 만 이미징 할 수있는 프로그램이 있습니다.


1
"dd를 사용한다면 항상 dd bs=1M" 처럼 기본 블록 크기보다 커야합니다 .-가능하지만 너무 많이 기대하지는 마십시오. 내 PC에서 dd512 바이트 블록으로 약 2GB / s를 수행합니다. 병목 현상이되지는 않습니다. gzip될거야.
marcelm

@marcelm 우리는 사람들이 어떤 종류의 기계를 사용하고 있는지 전혀 모른다. 이 경우 dd2 기가 바이트가는 /이 과정에서하지 최대 밖으로 하나의 CPU 코어를 100 % 그랬다면 내가 놀랄 것이다, 512 바이트 블록이야. 이제 상자가 유휴 상태 인 쿼드 코어 인 경우 차이를 느끼지 못할 수 있습니다. 그래도 다른 사람들은 여전히 ​​그렇습니다.
frostschutz

9
한숨. dd블록 크기가 언급 될 때마다 사람들은 아물지 않습니다. gzipCPU 집약적 인 것도 내 대답의 일부였습니다. 그리고 미안, 나는 "무시할 수있는"것에 동의하지 않는다. 그것은 공연 당 1-2s를 추가 할 수 gzip -9있지만 (수백 개의 공연을 처리 할 때 여전히 몇 분이 소요됩니다) lzop -1공연 당 1s 대 공연 당 4s로 조언을 구 하십시오. 감자 (단일 코어 가상 서버)에서 테스트했습니다. 적절한 블록 크기를 추가하면 dd비용이 들지 않으며 단점이 없습니다. nitpick하지 마십시오. 그냥 해. ymmv
frostschutz

19

dd한 번에 한 블록 씩 데이터를 읽고 씁니다. 그래서

valgrind dd if=/dev/zero status=progress of=/dev/null bs=1M

dd약 1MB의 메모리 를 사용 하는 것을 보여줍니다 . 당신은 블록 크기로 놀아서 떨어 뜨릴 수 valgrind있으며, dd속도 에 미치는 영향을 볼 수 있습니다.

에 당신 파이프 때 gzip, dd단순히 일치 둔화 gzip의 속도를. 메모리 사용량이 증가하지 않으며 커널이 디스크에 버퍼를 저장하지도 않습니다 (커널은 스왑을 통한 경우 제외하고는이 수행하는 방법을 모릅니다 ). 부러진 파이프는 파이프 끝 중 하나가 죽을 때만 발생합니다. 참조 signal(7)write(2)자세한 내용은.

그러므로

dd if=... iconv=fullblock bs=1M | gzip -9 > ...

당신이 쫓는 일을하는 안전한 방법입니다.

파이핑 할 때 읽기 프로세스가 계속 진행되지 않으면 쓰기 프로세스가 커널에 의해 차단됩니다. 당신은 이것을 실행하여 이것을 볼 수 있습니다

strace dd if=/dev/zero bs=1M | (sleep 60; cat > /dev/null)

dd1MB 를 읽은 다음 실행 write()하는 동안 1 분 동안 대기 하는 것을 발행 sleep합니다. 파이프의 양쪽이 균형을 잡는 방법입니다. 쓰기 프로세스가 너무 빠르면 커널이 쓰기를 차단하고 읽기 프로세스가 너무 빠르면 읽기를 차단합니다.


1
꽤 괜찮은데. 어떤 메커니즘 dd을 통해 속도와 일치하도록 gzip속도를 늦추는가? 커널과 같이 자동이거나 출력 파일 디스크립터에 대한 메타 데이터로부터 계산합니까?
cat

9
@cat 자동입니다. 파이프에 데이터를 넣는 dd호출 write(). write()실제로 파이프 메모리를 조작 할 수 있도록 제어를 커널로 전송합니다. 커널에 파이프가 가득 차면 파이프에 충분한 공간이 생길 때까지 기다립니다 ( "차단"). 그런 다음에 만 write()통화가 완료되고 제어가로 다시 전송 dd되어 파이프에 데이터를 다시 씁니다.
marcelm

9

성능 이외의 부정적인 영향은 없습니다. 파이프에는 일반적으로 64K 인 버퍼가 있으며 그 후 파이프에 대한 쓰기는 gzip더 많은 데이터를 읽을 때까지 단순히 차단 됩니다.


8

어떻게 작동하는지에 대한 실제 질문에 대답하기 : "왼쪽의 프로그램이 파이프의 다른 쪽보다 더 많은 데이터를 더 빨리 쓰면 어떻게 처리하겠습니까?"

이런 일은 일어나지 않습니다. 파이프에는 상당히 작고 제한된 크기의 버퍼가 있습니다. 참조 큰 파이프 버퍼 얼마나?

파이프 버퍼가 가득 차면 전송 프로그램이 차단 됩니다. 쓰기 호출을하면 커널은 데이터가 버퍼에 쓰여질 때까지 프로그램에 대한 제어를 반환하지 않습니다. 버퍼를 비울 수있는 읽기 프로그램 CPU 시간을 제공합니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.