dd vs cat — dd는 요즘에도 여전히 관련이 있습니까?


122

나는 최근에 우리가 사용할 수있는 실현 cat만큼 dd, 그리고 그건 사실보다 더 빨리dd

dd성능이 아니라 블록 크기가 실제로 올바른 테이프를 처리하는 데 유용하다는 것을 알고 있습니다. 하지만 요즘에는 dd무언가 cat할 수없는 상황이 있습니까? (여기서는 성능 차이가 20 % 미만인 것으로 간주합니다.)

구체적인 예는 좋을 것입니다!


1
구체적인 예는 이 SO 질문 을 참조하십시오 .
camh

답변:


156

외관상으로 dd는 IBM 운영 체제의 도구로 외래 모양 (매개 변수 전달)을 유지하는 도구로 거의 사용되지 않는 기능 (예 : EBCDIC에서 ASCII 로의 변환 또는 엔디안 반전 등)을 수행합니다.

내가 생각하는 데 사용 하는이 dd빠른 (때문에 버퍼링을보다 효율적으로 사용) 같은 디스크에 대량의 데이터 블록을 복사하는이었다, 그러나 이것은 사실이 아니다 적어도 오늘날의 리눅스 시스템에서.

필자 dd는 실제로 블록 단위로 읽기가 수행되는 테이프를 다룰 때 일부 옵션이 유용 하다고 생각 합니다 (테이프 드라이버는 디스크 드라이버처럼 저장 매체의 블록을 숨기지 않습니다). 그러나 나는 구체적인 내용을 모른다.

dd다른 POSIX 도구로 (쉽게) 수행 할 수없는 한 가지 작업 은 스트림 의 첫 N 바이트취하는 것 입니다. 많은 시스템에서이 기능을 수행 할 수 head -c 42있지만 head -c, 일반적으로 POSIX에는 없지만 OpenBSD에서는 현재 사용할 수 없습니다. ( tail -cPOSIX입니다.) 또한 head -c존재하는 경우에도 소스에서 너무 많은 바이트를 읽을 수 있습니다 (내부에서는 stdio 버퍼링을 사용하기 때문에). 읽기만하는 특수 파일에서 읽는 경우 문제가됩니다. (현재 GNU coreutils는로 정확한 개수를 읽지 head -c만 FreeBSD와 NetBSD는 stdio를 사용합니다.)

더 일반적으로, dd유닉스 도구 사이에 고유 한 기본 파일 API에 대한 인터페이스를 제공합니다에만 dd할 수 덮어 쓰거나 잘라 파일을 언제든지 또는 추구 파일에. (이것은 dd고유 한 능력이며 큰 기능입니다. 이상하게도 dd다른 도구가 할 수있는 것으로 잘 알려져 있습니다.)

  • 대부분의 유닉스 도구는 출력 파일을 덮어 씁니다. 즉, 내용을 지우고 처음부터 다시 시작합니다. 이것은 >쉘에서도 리디렉션 을 사용할 때 발생 합니다.
  • >>쉘에서 경로 재 지정 또는 을 사용하여 파일 내용에 추가 할 수 있습니다 tee -a.
  • 특정 지점 이후에 모든 데이터를 제거하여 파일을 줄이려 면 truncate함수를 통해 기본 커널 및 C API에서 지원 하지만 다음을 제외한dd 모든 명령 줄 도구에는 노출되지 않습니다 .

    dd if=/dev/null of=/file/to/truncate seek=1 bs=123456  # truncate file to 123456 bytes
    
  • 파일 중간에 데이터를 덮어 쓰려면 다시 잘라 내지 않고 파일을 열어 ( lseek필요한 경우 원하는 위치로 이동하도록 호출) 파일을 열어 언더 실링 API에서이 작업을 수행 dd할 수 있습니다. 절단 또는 추가하거나, 시크 쉘 (부터 보다 복잡한 예 ).

    # zero out the second kB block in the file (i.e. bytes 1024 to 2047)
    dd if=/dev/zero of=/path/to/file bs=1024 seek=1 count=1 conv=notrunc
    

그래서… 시스템 도구로서 dd거의 쓸모가 없습니다. 텍스트 (또는 이진 파일) 처리 도구로서 매우 유용합니다!


나는 그것이 다른 답변 (의 요점을 설명 생각하기 때문에 허용 truncseek에서 사용할 수있는이 dd).
kizzx2

2
한 가지 더 특별한 용도 : ddstdio 버퍼링으로 인해 읽지 않은 데이터를 잠재적으로 파괴하지 않고도 검색 할 수없는 파일 디스크립터에서 이진 데이터를 읽을 수 있습니다. 예를 보려면 여기를 참조하십시오 : etalabs.net/sh_tricks.html
R ..

2
@R .. : 예. GNU에서 6.10로 coreutils head -c N전화를 read결코 NetBSD의 5.1 N. 넘어 간다, head -c호출합니다 getc. FreeBSD 7.4에서는를 head -c호출합니다 fread.
Gilles

1
Coreutils dd는 O_DIRECT 등을 쉘 스크립팅에 노출시킵니다.
derobert

1
Coreutils를 truncate사용하면 파일을 자르 거나 확장 할 수 있으므로을 다시 사용할 필요가 없습니다 dd.
dcoles

22

dd명령에는 cat이 수용 할 수없는 많은 옵션이 포함됩니다. 아마도 귀하의 사용 사례에서 고양이는 실행 가능한 대체물이지만 dd 대체물은 아닙니다.

한 가지 예는 dd무언가의 일부는 복사하지만 전부는 복사하지 않는 데 사용 됩니다. 아마도 장치의 알려진 위치에 따라 하드 드라이브에서 iso 이미지의 중간 부분이나 파티션 테이블의 일부 비트를 제거하려고 할 수 있습니다. 으로 dd당신이 시작을 지정할 수 있습니다 중지하고 이러한 작업을 가능 수량 옵션을 제공합니다.

이 옵션을 dd사용하면 세밀한 데이터 조작에 반드시 필요한 반면 cat*는 전체 파일 객체, 장치 또는 스트림에서만 작동 할 수 있습니다.

* Gilles의 의견에서 언급했듯이 cat다른 도구와 결합 하여 무언가의 일부를 분리 할 수는 있지만 cat여전히 전체 객체에서 작동합니다.


5
dd실제로는 저수준 장치와 관련이 없으며 /dev다른 장치 와 같은 항목이 필요합니다 . 로 전체 파티션을 복사 cat하거나로 일부를 복사 할 수 있습니다 tail +c $(($start+1)) | head -c $count.
Gilles

16
물론이야. ;-) 그리고 cat | head | tail마지막 몇 MB를 가져 오기 위해 1.6TB 디스크 이미지를 공급 하면 디스크 회전이 지구에 더 가까이 달을 빨아들입니다.
Caleb

2
@Gilles 죄송합니다. 장치가 아닌 장치의 데이터를 언급하고 있지만 "낮은 수준"이라는 용어를 사용하는 것은 그리 좋은 말이 아니라는 점을 인정했습니다. 아마도 "미세 조정 된 데이터 조작"이 "낮은 레벨의 데이터 조작"보다 낫습니다.
Caleb

21

아무도 아직 작성 DD를 사용할 수있는 언급하지 않았다 스파 스 파일을 하지만, truncate같은 목적을 위해 이용 될 수있다.

dd if=/dev/zero of=sparse-file bs=1 count=1 seek=10GB

이것은 거의 즉각적이며 예를 들어 루프백 파일로 사용할 수있는 임의의 큰 파일을 만듭니다.

loop=`losetup --show -f sparse-file`
mkfs.ext4 $loop
mkdir myloop
mount $loop myloop

좋은 점은 처음에는 하나의 디스크 공간 블록 만 사용하고 나서 필요한만큼만 증가한다는 것입니다 (10GB 파일의 4 번째 형식은 시스템에서 291MB를 소비 함). 사용 du- 실제로 사용되는 디스크 공간을 보려면 ls보고서에만 최대 크기는 파일로 성장할 수 있습니다.


4
ls -ls희소 크기를 보여줍니다.
jmtd

2
명령이 쓸모없는 바이트를 파일에 씁니다. dd of=sparse-file bs=1 count=0 seek=10G와 같습니다 truncate -s 10GB sparse-file. 혼동 충분 truncate하고 dd정확한 반대 해석이 GB대를 G...
frostschutz

5
@frostschutz : man dd말한다 : MB =1000*1000, M =1024*1024등등. 그리고 man truncate말합니다 : MB 1000*1000, M 1024*1024그렇기 때문에 아무런 차이없습니다. GNU coreutils ddtruncateGNU coreutils를 모두 사용합니다 . 당신도 그렇게해야합니다! :-)
erik

@ 에릭 : 수정 주셔서 감사합니다. 최근에 변경되지 않았다면 어떻게 든 다른 것과 혼동해야합니다.
frostschutz 2016

10

하드 드라이브의 특정 부분을 다른 것으로 재정의하는 것이 일반적인 예입니다. 예를 들어 다음 명령을 사용하여 MBR을 삭제하려고 할 수 있습니다.

dd if=/dev/zero of=/dev/sda bs=446 count=1

또한 빈 파일을 만들 수 있습니다 (예 : 루프 디스크 이미지).

dd if=/dev/zero of=10mb.file bs=1024k count=10

따로, 두 번째 명령은 10MB를 사용하는 가장 빠른 방법입니다.
Kevin M

3
@Kevin :보다 빠릅니다 head -c. 벤치 마크를 공유하십시오 !
Gilles

9

dd하드 드라이브 또는 다른 저장 장치의 부팅 섹터를 백업 dd if=/dev/sda of=boot_sector.bin bs=512 count=1한 다음 나중에 다시 쓰는 데 매우 유용 합니다 ( dd if=boot_sector.bin of=/dev/sda). 암호화 된 볼륨의 헤더를 백업 할 때도 유용합니다.

cat그렇게 할 수는 있지만 재 작성 부분에서는 그것을 믿지 않을 것입니다. cat특정 바이트 수만 읽고 쓰기 가 어렵습니다 .


5

필자는 최근 리눅스 역사상 처음으로 몇 백 GB 용량의 파티션을 복제해야하는 원인이 있었다 (참고로 cp -ar또는 rsync여러 번 나에게 도움이 되었음 ). 물론 나는 dd'모든 사람들이 그것이 당신이 사용하는 것을 알고 있음을 알고 있습니다. 약간의 인터넷 검색으로 인해 나를 ddrescue몇 번이나 사용했으며 훌륭하게 잘 작동했습니다 (dd보다 훨씬 빠름).


1
ddrescue특히 장애가 발생한 디스크에서 데이터를 가져 오는 데 유용합니다.
ryenus

5

몇 년 동안 내가 생각해 낸 dd 트릭은 다음과 같습니다.

비 친화적 인 tty 또는 비 대화식 모드 bash에서 잘라 내기 및 붙여 넣기

EOF / ^ D / ^ F가 감지되지 않는 경우 dd를 사용하여 텍스트 파일을 호스트로 전송할 수 있습니다. 지정된 양의 바이트 후에 자동으로 읽기를 중지하기 때문입니다.

나는 작년에 원격 호스트에서 tty가 아닌 쉘을 얻을 수 있고 파일을 전송 해야하는 보안 연습 중에 최근에 이것을 사용했습니다.

사실, 나는 바이너리 파일을 base64로 인코딩하고 느리지 만 안정적인 pure-bash base64 디코딩 스크립트를 사용하여 바이너리 파일을 만들었습니다.

dd of=textfile.txt bs=1 count=<size_of_data_in_paste_buffer>

매우 멋진 트릭은 dd가 실행되는 동안 USR1 신호를 보내면 현재 상태 (바이트 읽기, 초당 바이트)를 방출한다는 것입니다.

범용 처리량 상태 필터

나는 stdout을 통해 데이터를 내보내는 모든 프로그램에 대한 순수한 bash 진행 필터로 작동하도록 이것을 썼습니다. (참고 : 거의 모든 것은 stdout을 통해 데이터를 방출합니다. 바이트 수, 인쇄 해시 표시 (해시 모드가 설정된 경우 올드 스쿨 FTP 등)

(주) 진행 파일은 절름발이입니다. 이것은 대부분 개념 증명입니다. 다시 수정하면 변수를 사용합니다.

 dd bs=$BLKSZ of=${TMPFILE} 2>&1 \
                | grep --line-buffered -E '[[:digit:]]* bytes' \
                | awk '{ print $1 }' >> ${PROGRESS} &

 while [[ $(pidof dd) -gt 1 ]]; do

        # PROTIP: You can sleep partial seconds
        sleep .5

        # Force dd to update us on it's progress (which gets
        # redirected to $PROGRESS file.    
        pkill -USR1 dd
        local BYTES_THIS_CYCLE=$(tail -1 $PROGRESS)
        local XFER_BLKS=$(((BYTES_THIS_CYCLE-BYTES_LAST_CYCLE)/BLKSZ))

        if [ $XFER_BLKS -gt 0 ]; then
                printf "#%0.s" $(seq 0 $XFER_BLKS)
                BYTES_LAST_CYCLE=$BYTES_THIS_CYCLE
        fi
done

익명 쉘 파일 핸들을 사용하는 슬라이스 앤 다이스 파일

다음은 tmp 파일을 사용하여 부분 파일 데이터를 저장하지 않고 익명의 파일 핸들을 통해 tar 입력을 제공하여 오류없이 추출 할 수있는 서명 된 tar 파일을 얻는 방법에 대한 의사 코드 예입니다.

generate_hash() {
    echo "yay!"
}

# Create a tar file, generate a hash, append it to the end
tar -cf log.tar /var/log/* 2>/dev/null
TARFILE_SIZE=$(stat -f "%z" log.tar)
SIGNATURE=$(generate_hash log.tar)
echo $SIGNATURE >>log.tar

# Then, later, extract without getting an error..

tar xvf <(dd if=$OLDPWD/log.tar bs=1 count=${TARFILE_SIZE})

tl; dr는 : dd가 매우 유용하다는 것을 알았습니다. 그리고 이것은 제가 머리 꼭대기에서 생각할 수있는 세 가지 예일뿐입니다.


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