디스크가 가득 찰 때까지`tar`를`dd`로 파이핑하는 이유는 무엇입니까? 192M Okt 5 00:53 $ tar

단일 디스크 이미지의 tar 아카이브가 있습니다. 이 tar 파일의 이미지 크기는 약 4GB입니다. I 파이프의 출력 tar xfddSD 카드에 디스크 이미지를 작성한다. 카드가 가득 찰 때까지 디스크 덤프는 중지되지 않습니다. 내 셸 세션은 다음과 같습니다.

$ 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 카트에 쓴 후에는 중지되고 공간이 부족하지 않습니다!



답변

당신이 잘못하고 있기 때문입니다.

사용하고 bs=1M있지만 stdin 파이프에서 읽는 것은 더 작은 읽기를 갖습니다. 실제로, dd에 따르면, 당신은 하나의 전체 읽기를 얻지 못했습니다.

그런 다음 conv=sync불완전한 읽기를 0으로 보완하는 것이 있습니다 .

0+15281 records in
15280+0 records out

dd0 전체 및 15281 불완전한 읽기를 수신하고 15280 전체 블록을 썼습니다 (conv = sync zero filled). 따라서 공간이 남지 않을 때까지 출력이 입력보다 훨씬 큽니다.

   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을 쓰는 것과 같이 환영받을만한 경우에도 문제가 심각하게 잘못됩니다.


답변