Tóm tắt: dd
là một công cụ cáu kỉnh, khó sử dụng chính xác. Đừng sử dụng nó, mặc dù có rất nhiều hướng dẫn cho bạn biết như vậy. dd
có một điểm đáng tin cậy trên đường phố của người Anh gắn liền với nó - nhưng nếu bạn thực sự hiểu những gì bạn đang làm, bạn sẽ biết rằng bạn không nên chạm vào nó với một cột 10 feet.
dd
thực hiện một cuộc gọi đến cuộc gọi read
hệ thống trên mỗi khối (được xác định bởi giá trị của bs
). Không có gì đảm bảo rằng read
cuộc gọi hệ thống trả về nhiều dữ liệu như kích thước bộ đệm đã chỉ định. Điều này có xu hướng hoạt động cho các tệp thông thường và các thiết bị chặn, nhưng không phải cho các đường ống và một số thiết bị ký tự. Xem Khi nào dd phù hợp để sao chép dữ liệu? (hoặc, khi được đọc () và viết () một phần) để biết thêm thông tin. Nếu read
cuộc gọi hệ thống trả về ít hơn một khối đầy đủ, sau đó dd
chuyển một phần khối. Nó vẫn sao chép số lượng khối được chỉ định, do đó tổng số byte được truyền ít hơn yêu cầu.
Cảnh báo về việc đọc một phần của người Viking cho bạn biết chính xác điều này: một trong những lần đọc là một phần, do đó đã dd
chuyển một khối không hoàn chỉnh. Trong số đếm khối, +1
có nghĩa là một khối đã được đọc một phần; vì số lượng đầu ra là +0
, tất cả các khối được viết ra là đã đọc.
Điều này không ảnh hưởng đến tính ngẫu nhiên của dữ liệu: tất cả các byte dd
ghi ra là các byte mà nó đọc từ đó /dev/urandom
. Nhưng bạn có ít byte hơn dự kiến.
Linux cung /dev/urandom
cấp các yêu cầu lớn tùy ý (nguồn: extract_entropy_user
in drivers/char/random.c
), do đó dd
thường an toàn khi đọc từ nó. Tuy nhiên, đọc số lượng lớn dữ liệu cần có thời gian. Nếu quá trình nhận được tín hiệu, read
cuộc gọi hệ thống trả về trước khi điền vào bộ đệm đầu ra của nó. Đây là hành vi bình thường và các ứng dụng được yêu cầu gọi read
theo vòng lặp; dd
không làm điều này, vì lý do lịch sử ( dd
nguồn gốc là âm u, nhưng dường như nó đã bắt đầu như một công cụ để truy cập băng, có yêu cầu đặc biệt, và không bao giờ được điều chỉnh thành một công cụ đa năng). Khi bạn kiểm tra tiến trình, điều này sẽ gửi dd
quá trình tín hiệu làm gián đoạn việc đọc. Bạn có một sự lựa chọn giữa việc biết có bao nhiêu bytedd
sẽ sao chép toàn bộ (đảm bảo không làm gián đoạn nó - không kiểm tra tiến trình, không đình chỉ) hoặc biết có bao nhiêu byte dd
đã được sao chép cho đến nay, trong trường hợp đó bạn không thể biết mình sẽ sao chép thêm bao nhiêu byte.
Phiên bản dd
trong lõi core GNU (như được tìm thấy trên Linux không được nhúng và trên Cygwin) có một cờ fullblock
cho biết dd
để gọi read
trong một vòng lặp (và ditto cho write
) và do đó luôn chuyển các khối đầy đủ. Thông báo lỗi cho thấy bạn sử dụng nó; bạn nên luôn luôn sử dụng nó (trong cả cờ đầu vào và đầu ra), ngoại trừ trong những trường hợp rất đặc biệt (chủ yếu là khi truy cập băng) - nếu bạn sử dụng dd
tất cả, đó là: thường có giải pháp tốt hơn (xem bên dưới).
dd if=/dev/urandom iflag=fullblock oflag=fullblock of=file bs=1M count=1000000
Một cách khác có thể để chắc chắn về những gì dd
sẽ làm là vượt qua kích thước khối 1. Sau đó, bạn có thể cho biết có bao nhiêu byte đã được sao chép từ số khối, mặc dù tôi không chắc điều gì sẽ xảy ra nếu read
bị gián đoạn trước khi đọc lần đầu tiên byte (không có nhiều khả năng trong thực tế nhưng có thể xảy ra). Tuy nhiên, ngay cả khi nó hoạt động, điều này rất chậm.
Lời khuyên chung về việc sử dụng dd
là không sử dụngdd
. Mặc dù dd
thường được quảng cáo là một lệnh cấp thấp để truy cập các thiết bị, nhưng thực tế không phải vậy: tất cả các phép thuật xảy ra trong phần (tệp /dev/…
) của thiết bị , dd
chỉ là một công cụ thông thường có khả năng lạm dụng cao dẫn đến mất dữ liệu . Trong hầu hết các trường hợp, có một cách đơn giản và an toàn hơn để làm những gì bạn muốn, ít nhất là trên Linux.
Ví dụ, để đọc một số byte nhất định ở đầu tệp, chỉ cần gọi head
:
head -c 1000000m </dev/urandom >file
Tôi đã tạo một điểm chuẩn nhanh trên máy của mình và không quan sát thấy bất kỳ sự khác biệt hiệu suất nào giữa dd
kích thước khối lớn và head
.
Nếu bạn cần bỏ qua một số byte lúc đầu, hãy tail
chuyển sang head
:
dd if=input of=output count=C bs=B seek=S
<input tail -c +$((S*B+1)) | head -c $((C*B)) >output
Nếu bạn muốn xem tiến trình, hãy gọi lsof
để xem tập tin bù. Điều này chỉ hoạt động trên một tệp thông thường (tệp đầu ra trên ví dụ của bạn), không phải trên một thiết bị ký tự.
lsof -a -p 1234 -d 1
cat /proc/1234/fdinfo/1
Bạn có thể gọi pv
để nhận báo cáo tiến độ (tốt hơn so với dd
), với chi phí của một mục bổ sung trong đường ống (thông minh về hiệu suất, hầu như không nhận thấy được).