dd로 임의의 데이터를 생성하고 "부분 읽기 경고"를 얻습니다. 경고 후의 데이터는 이제 무작위입니까?


16

와 함께 임의의 데이터로 1TB 파일을 만듭니다 dd if=/dev/urandom of=file bs=1M count=1000000. 이제 kill -SIGUSR1 <PID>진행 상황을 확인하고 다음을 얻습니다.

691581+0 Datensätze ein
691580+0 Datensätze aus
725174190080 Bytes (725 GB) kopiert, 86256,9 s, 8,4 MB/s
800950+1 Datensätze ein
800950+0 Datensätze aus
839856947200 Bytes (840 GB) kopiert, 99429,5 s, 8,4 MB/s
dd: warning: partial read (809620 bytes); suggest iflag=fullblock
803432+1 Datensätze ein
803431+1 Datensätze aus
842459273876 Bytes (842 GB) kopiert, 99791,3 s, 8,4 MB/s

경고를 해석 할 수 없습니다. 그것은 무엇을 말하는가? 경고 후 내 파일이 실제로 무작위입니까, 아니면 문제가 있습니까? 무엇 0 또는 1의 수행 800950+1 Datensätze ein800950+0 Datensätze aus평균? 경고 후 +1입니다. 오류 횟수입니까?


메시지를 영어로 번역 할 수 있다면 대답하기가 더 쉬울 것입니다. 또한 "정말 임의"를 정의하십시오. 어느 수준의 임의성이 필요합니까? 어떻게 사용합니까?
terdon

영어 메시지를 받으려면 다음 LC_ALL=C과 같이 명령 앞에 사용하십시오 .LC_ALL=C dd if=...
Volker Siegel

답변:


38

요약 : dd제대로 사용하기 어려운 까다로운 도구입니다. 수많은 자습서에도 불구하고 사용하지 마십시오. dd"unix street cred"바이브가 부착되어 있습니다.하지만 당신이하고있는 일을 진정으로 이해한다면, 10 피트 기둥으로 만지면 안된다는 것을 알게 될 것입니다.

ddread블록 당 시스템 호출을 단일 호출합니다 (값으로 정의 됨 bs). read시스템 호출이 지정된 버퍼 크기만큼 많은 데이터를 리턴 한다는 보장은 없습니다 . 이것은 일반 파일 및 블록 장치에서는 작동하지만 파이프 및 일부 문자 장치에서는 작동하지 않습니다. dd가 데이터 복사에 적합한시기를 참조하십시오 . 자세한 내용 은 read () 및 write () 부분 일 때 경우 read시스템 호출이 반환 미만 전체 블록, 다음 dd부분 블록을 전송합니다. 여전히 지정된 수의 블록을 복사하므로 전송 된 총 바이트 수가 요청 된 것보다 적습니다.

"부분 읽기"에 대한 경고는 정확하게 이것을 알려줍니다. 읽기 중 하나는 부분적이므로 dd불완전한 블록으로 전송되었습니다. 블록 카운트에서 +1하나의 블록을 부분적으로 읽었 음을 의미합니다. 출력 카운트가 +0이므로 모든 블록을 읽은 상태로 기록했습니다.

이것은 데이터의 임의성에 영향을 미치지 않습니다. dd기록하는 모든 바이트 는에서 읽은 바이트입니다 /dev/urandom. 그러나 예상보다 적은 바이트를 얻었습니다.

Linux는 /dev/urandom임의의 큰 요청 (source : extract_entropy_userin drivers/char/random.c)을 수용하므로 dd일반적으로 읽을 때 안전합니다. 그러나 많은 양의 데이터를 읽으려면 시간이 걸립니다. 프로세스가 신호를 수신하면 read출력 버퍼를 채우기 전에 시스템 호출이 리턴됩니다. 이것은 정상적인 동작이며 응용 프로그램은 read루프 를 호출해야합니다 . dd역사적인 이유로 (이것은 dd출처가 어둡지 만, 독특한 요구 사항을 가지고 있으며 범용 도구로 채택되지 않은 테이프에 액세스하는 도구로 시작된 것으로 보입니다). 진행 상황을 확인하면 dd프로세스에 읽기를 방해하는 신호를 보냅니다 . 바이트 수를 아는 것 중에서 선택할 수 있습니다dd전체 복사 (진행 확인, 일시 중단 없음) 또는 dd지금까지 얼마나 많은 바이트 가 복사 되었는지 아는 경우 복사 할 바이트 수를 알 수 없습니다.

버전 ddGNU의로 coreutils에서 (Cygwin에서 비 임베디드 리눅스와에 발견은) 플래그가 fullblock알려줍니다 dd호출 read(및 저두 루프 write) 때문에 항상 전체 블록을 전송합니다. 오류 메시지는 사용을 제안합니다. 매우 특수한 상황 (주로 테이프에 액세스 할 때)을 제외하고는 항상 (입력 및 출력 플래그 모두) 사용해야합니다 dd. 전혀 사용하지 않는 경우 : 일반적으로 더 나은 솔루션이 있습니다 (아래 참조).

dd if=/dev/urandom iflag=fullblock oflag=fullblock of=file bs=1M count=1000000

dd수행 할 작업을 확인하는 또 다른 가능한 방법 은 블록 크기 1을 전달하는 것입니다. 그런 다음 read첫 번째를 읽기 전에 a 가 중단 되면 어떻게 될지 잘 모르겠지만 블록 수에서 복사 된 바이트 수를 알 수 있습니다 바이트 (실제로는 아니지만 가능성이 있음). 그러나 작동하더라도 매우 느립니다.

사용에 대한 일반적인 조언 dd이다 사용하지 마십시오dd . 하지만 dd모든 마법이 장치 파일합니다 (에서 일어나는 : 자주 액세스 장치에 낮은 수준의 명령으로 광고, 그것은 사실 그런 일에 /dev/…) 일부 dd데이터 손실의 결과로 오용에 대한 높은 잠재력을 가진 평범한 도구입니다 . 대부분의 경우 최소한 Linux에서는 원하는 것을 간단하고 안전하게 수행 할 수 있습니다.

예를 들어, 파일의 시작 부분에서 특정 바이트 수를 읽으려면 다음을 호출하십시오 head.

head -c 1000000m </dev/urandom >file

내 컴퓨터에서 빠른 벤치 마크를 수행 dd했으며 큰 블록 크기와와의 성능 차이가 관찰되지 않았습니다 head.

당신이 처음에 몇개의 바이트를 건너해야하는 경우, 파이프 tailhead:

dd if=input of=output count=C bs=B seek=S
<input tail -c +$((S*B+1)) | head -c $((C*B)) >output

진행 상황 lsof을 보려면 파일 오프셋을 보려면 전화 하십시오. 이것은 문자 장치가 아닌 일반 파일 (예제의 출력 파일)에서만 작동합니다.

lsof -a -p 1234 -d 1
cat /proc/1234/fdinfo/1

파이프 라인의 추가 항목 (성능 측면에서는 거의 인식 할 수 없음)을 희생하면서 pv진행 보고서 (보다 큼)를 얻기 위해 전화 할 수 있습니다 dd.


2
+1. 이것은 내가 오랫동안 Exchange Exchange 네트워크에서 읽은 가장 잘 연구 된 게시물 중 하나입니다. 간결하면서도 dd알아야 할 명령 에 대한 모든 세부 사항 (역사 및 현재)이 포함되어 있습니다 . 감사.
우주 Ossifrage

4
죄송합니다. dd는 "정확하게 사용하기 어려운 까다로운 도구"이며 "dd를 사용하지 마십시오"라는 귀하의 주장에 동의하지 않습니다. 시간을내어 이해 한 사람이 올바르게 사용하면 완벽하게 훌륭한 유틸리티입니다. 실제로 디스크 포렌식 툴킷은 거의 모두 dd 또는 dcfldd와 같은 파생물에 의존합니다.
fpmurphy

1
@ fpmurphy1 GNU ddfullblock옵션 덕분에 안전하게 사용할 수 있습니다 . 그러나 GNU coreutils가 있다면별로 필요하지 않습니다 dd. "파생 상품"은 다음과 같은 dcfldd되어 있지 dd 내 대답은 그들에게 적용되지 않도록, 그들은 그것의 디자인 결함으로 고생하지 않습니다. 사용하는 광대하고 대다수의 사람들은 dd그것을 이해하는 데 충분한 시간을 소비하지 않았으며 (대부분은 이해 한다고 생각 하는 데 시간이 걸렸 습니다) 데이터를 사용하는 방식은 데이터 손실로 이어집니다.
Gilles 'SO- 악한 중지'

1
@Gilles 그래서 우리는 오용의 가능성을 가진 "echo"b / c를 사용해서는 안됩니다 (sudo echo hello world> / dev / sda)?
whitey04

2
@ whitey04 니트로 글리세린 배럴을 취급하지 않는 것이 좋습니다. 나는 당신이 성냥을 사용해서는 안된다고 말하지 않았습니다.
Gilles 'SO- 악마 그만해'

9

dd단일 읽기에서 블록을 채우기에 충분한 데이터를 얻을 수 없을 때 경고가 발생합니다 . 이는 불규칙하거나 느린 데이터 소스 또는 요청 된 블록 크기보다 작은 단위로 데이터를 쓰는 소스에서 발생합니다.

데이터 무결성에는 문제가 없지만 dd부분 읽기는 여전히 읽기 블록으로 간주됩니다.

count옵션을 사용하지 않는 경우 경고는 거의 중요 하지 않으며 성능 고려 사항 일뿐입니다. 그러나을 (를) 사용 count하면 요청한 데이터 양을 얻을 수 없습니다. 부분 읽기로 인해 끝 of보다 작습니다 count*bs.

따라서를 사용할 count때는 기술적으로 항상 사용해야 iflag=fullblock합니다.

+x부분 블록의 개수이어야한다.


-3
< /dev/urandom \
dd ibs=4k obs=64k |
dd bs=64k count=16000000 >file

^ 그냥 작동합니다. 그렇지 않은 경우 잘못된 정보는 명백히 거짓입니다. dd의 버퍼는 명시 적이므로 발생 을 계산 하기 위해 입력을 버퍼링하려면 명시 적으로 버퍼링해야합니다. 그게 다야 똥을 사지 마십시오.

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