디스크가 가득 찰 때까지 `tar`를 `dd`로 파이프하는 것이 중지되지 않는 이유는 무엇입니까?

디스크가 가득 찰 때까지 `tar`를 `dd`로 파이프하는 것이 중지되지 않는 이유는 무엇입니까?

단일 디스크 이미지의 tar 아카이브가 있습니다. tar 파일 내부의 이미지 크기는 약 4GB입니다. tar xf출력 dd을 SD 카드로 파이프합니다 . 카드가 가득 찰 때까지 디스크 덤프는 중지되지 않습니다. 이것은 내 쉘 세션입니다.

$ ls -l disk.img.tgz
-rw-r--r-- 1 confus confus 192M Okt  5 00:53

$ tar -tvf disk.img.tgz
-rw-r--r-- root/root 4294968320 2018-10-05 00:52 disk.img

$ lsblk -lb /dev/sdc
NAME MAJ:MIN RM        SIZE RO TYPE MOUNTPOINT
sdc    8:32   1 16022241280  0 disk

$ tar zxf disk.img.tgz -O | sudo dd status=progress conv=sync bs=1M of=/dev/sdc
[sudo] password for user: 
15992881152 bytes (16 GB, 15 GiB) copied, 212 s, 75,4 MB/s 
dd: error writing '/dev/sdc': No space left on device
0+15281 records in
15280+0 records out
16022241280 bytes (16 GB, 15 GiB) copied, 217,67 s, 73,6 MB/s

왜? 히트가 4GB 이미지를 16GB 카트에 쓴 후에는 중지되어야 하며 공간이 부족해지지 않습니다!

답변1

그건 당신이 잘못하고 있기 때문이에요.

사용하고 있지만 bs=1Mstdin, 파이프의 판독값은 더 작아집니다. 실제로 dd에 따르면 완전한 내용을 읽지 못합니다.

conv=sync그런 다음 불완전한 읽기를 0으로 채울 수 있습니다 .

0+15281 records in
15280+0 records out

dd0개의 완전한 읽기와 15281개의 불완전한 읽기가 수신되었으며 15280개의 완전한 블록이 기록되었습니다(conv=동기 제로 패딩). 따라서 남은 공간이 없을 때까지 출력은 입력보다 훨씬 큽니다.

   sync   pad  every  input  block  with  NULs to ibs-size; when used with
          block or unblock, pad with spaces rather than NULs

conv=sync이 문제를 해결하려면 를 제거 하고 추가하면 됩니다 iflag=fullblock.


이를 설명하기 위해 yes기본적으로 무한한 수의 "y\ny\ny\n"이 출력된다는 점을 고려하십시오.

$ yes
y
y
y
^C
$ yes | hexdump -C
00000000  79 0a 79 0a 79 0a 79 0a  79 0a 79 0a 79 0a 79 0a  |y.y.y.y.y.y.y.y.|
*

다음과 같습니다 dd bs=1M conv=sync.

$ yes | dd bs=1M conv=sync | hexdump -C
00000000  79 0a 79 0a 79 0a 79 0a  79 0a 79 0a 79 0a 79 0a  |y.y.y.y.y.y.y.y.|
*
0001e000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00100000  79 0a 79 0a 79 0a 79 0a  79 0a 79 0a 79 0a 79 0a  |y.y.y.y.y.y.y.y.|
*
00112000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*

따라서 불완전한 "y\ny\ny\n" 블록(0x00000 - 0x1e000, 122880바이트)을 얻은 다음 나머지 1M을 0(0x01e000 - 0x100000, 925696바이트)에 씁니다. 대부분의 경우 이러한 일이 발생하는 것을 원하지 않습니다. 그럼에도 불구하고 각 읽기가 얼마나 불완전한지 실제로 제어할 수 없기 때문에 결과는 무작위입니다. 여기서처럼 두 번째 읽기는 더 이상 122880바이트가 아니라 73728바이트입니다.

dd conv=sync읽기 오류가 발생했을 때 0을 쓰는 것과 같은 일반적인 상황에서도 거의 유용하지 않습니다.상황이 정말 나빠질 수 있습니다.

관련 정보