방금 이 질문에 부딪혔고 선택한 답변에서 많은 것을 배웠습니다.dd를 사용하여 임의의 데이터를 생성하고 "부분 읽기 경고"가 발생합니다. 이제 경고 이후의 데이터는 정말 무작위인가요?
불행하게도 제안된 솔루션 head -c
은 이식성이 없습니다.
dd
이것이 답변이라고 주장하는 분들은 링크된 답변을 주의 깊게 읽어보시기 바랍니다. 여기에는 왜 dd
답변이 될 수 없는지 자세히 설명되어 있습니다. 또한 다음 사항에 유의하세요.
$ dd bs=1000000 count=10 if=/dev/random of=random
dd: warning: partial read (89 bytes); suggest iflag=fullblock
0+10 records in
0+10 records out
143 bytes (143 B) copied, 99.3918 s, 0.0 kB/s
$ ls -l random ; du -kP random
-rw-rw-r-- 1 me me 143 Apr 22 19:19 random
4 random
$ pwd
/tmp
답변1
불행하게도 바이너리 파일의 내용을 조작하는 것은 dd
POSIX에서 사용할 수 있는 거의 유일한 도구입니다. 텍스트 처리 도구( cat
, sed
, , ...) 의 최신 구현은 awk
바이너리 파일에서 작동할 수 있지만 이는 POSIX 요구 사항이 아닙니다. 일부 이전 구현은 널 바이트, 줄 바꿈으로 종료되지 않은 입력 또는 잘못된 바이트로 인해 실패합니다. 환경 문자 블록 인코딩의 시퀀스입니다.
안전한 사용은 가능하지만 어렵습니다 dd
. 내가 사람들을 멀리하도록 많은 노력을 기울이는 이유는 dd
그것이 쓸모없고 안전하지 않을 때 그것을 홍보하는 많은 조언이 있기 때문입니다 .
문제는 dd
블록 개념입니다. 호출을 가정합니다.read
청크를 반환합니다. read
더 적은 양의 데이터가 반환되면 부분 청크를 얻게 되며, 이는 다음과 같은 것들을 skip
버립니다 count
. 다음 예에서는 dd
데이터를 상대적으로 느리게 전송하는 파이프에서 데이터를 읽는 문제를 보여줍니다.
yes hello | while read line; do echo $line; done | dd ibs=4 count=1000 | wc -c
습지 표준 Linux(Debian jessie, Linux 커널 3.16, dd
GNU coreutils 8.23)에서 내가 얻는 바이트 수는 약 3000에서 거의 4000까지 매우 다양합니다. 입력 블록 크기를 제수 6으로 변경하면 순진하게 예상한 대로 출력은 항상 4000바이트입니다. 입력은 dd
6바이트의 버스트로 도착하며 블록이 여러 버스트에 걸쳐 있지 않는 한 dd
괜찮습니다 . 완전한 블록.
이는 해결책을 제안합니다.입력 블록 크기 1 사용. 입력이 어떻게 생성되든 dd
입력 블록 크기가 1이면 부분 블록을 읽을 수 없습니다. (이것은 완전히 명확하지는 않습니다. dd
신호에 의해 중단되면 크기 0의 블록을 읽을 수 있습니다. 그러나 신호에 의해 중단되면 read
시스템 호출은 -1을 반환합니다. read
파일이 열린 경우에만 0을 반환할 수 있습니다. 비 차단 모드에서는 차단 모드에서만 파일 끝에서 0을 반환 한다고 생각하지 않는 것이 좋습니다 read
.read
dd ibs=1 count="$number_of_bytes"
이 접근 방식의 문제점은 속도가 느릴 수 있다는 것입니다(그러나 놀랄 만큼 느리지는 않습니다. head -c
빠른 벤치마크보다 약 4배 느릴 뿐입니다).
POSIX는 바이너리 데이터를 읽고 이를 텍스트 형식으로 변환하기 위한 추가 도구를 정의합니다.uuencode
(기록 uuencode 형식 또는 Base64로 출력),od
(8진수 또는 16진수 덤프를 출력합니다). 둘 다 현재 작업에 적합하지 않습니다. uuencode
이 작업은 다음으로 취소할 수 있습니다.uudecode
, 그러나 출력 라인당 바이트 수가 표준화되지 않았기 때문에 출력의 바이트 수를 계산하는 것이 어색합니다. 에서 잘 정의된 출력을 얻는 것이 가능 od
하지만 불행하게도 POSIX 도구는 그 반대 방향으로 수행할 수 없습니다(이 작업은 수행할 수 있지만 sh 또는 awk의 느린 루프를 통해서만 수행할 수 있으므로 여기서 목적을 달성할 수 없습니다).
답변2
최신 버전의 GNU 구현에는 iflag dd
가 있습니다 count_bytes
. 예를 들어:
cat /dev/zero | dd count=1234 iflag=count_bytes | wc -c
다음과 같이 출력됩니다
2+1 records in
2+1 records out
1234 bytes (1.2 kB, 1.2 KiB) copied, 0.000161684 s, 7.6 MB/s
1234
답변3
사용 목적 중 하나 dd
는 사용자가 사용하는 블록 크기를 선택할 수 있다는 것입니다. 블록 크기가 너무 커서 실패 하면 dd
더 작은 블록 크기를 시도하는 것은 IMO의 책임입니다. 테라바이트 단위의 블록을 요청할 수 있지만 dd
그렇다고 해서 얻을 수 있다는 의미는 아닙니다.
정확한 바이트 수를 원하는 경우 매우 느리지만 작동합니다.
dd bs=1 count=1000000
블록 크기라도 1
부분 읽기가 발생하면…