使用 dd 創建隨機數據並獲得“部分讀取警告”。現在警告後的數據真的是隨機的嗎?
我創建了一個包含隨機數據的 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 ein
什麼800950+0 Datensätze aus
意思?警告後為+1。是錯誤計數嗎?
摘要:
dd
是一個難以正確使用的古怪工具。不要使用它,儘管有很多教程告訴你。dd
有一種“unix street cred”的感覺——但如果你真正了解你在做什麼,你就會知道你不應該用一根 10 英尺長的桿子來觸摸它。
dd
每個塊對系統呼叫進行一次呼叫read
(由 的值定義bs
)。無法保證read
系統呼叫返回與指定緩衝區大小一樣多的數據。這往往適用於正常文件和塊設備,但不適用於管道和某些字元設備。請參閱dd 何時適合複製數據?(或者,何時是 read() 和 write() 部分)以獲取更多資訊。如果read
系統呼叫返回少於一個完整塊,則dd
傳輸部分塊。它仍然複製指定數量的塊,因此傳輸的總字節數少於請求的字節數。關於“部分讀取”的警告準確地告訴您:其中一個讀取是部分的,因此
dd
傳輸了一個不完整的塊。在塊計數中,+1
表示一個塊被部分讀取;由於輸出計數為+0
,所有塊都被寫為已讀。這不會影響數據的隨機性:所有
dd
寫出的字節都是它從中讀取的字節/dev/urandom
。但是你得到的字節比預期的要少。Linux
/dev/urandom
可容納任意大請求(來源:extract_entropy_user
indrivers/char/random.c
),因此dd
在讀取時通常是安全的。但是,讀取大量數據需要時間。如果程序接收到信號,read
系統呼叫會在填充其輸出緩衝區之前返回。這是正常行為,應用程序應該read
循環呼叫;dd
由於歷史原因,不這樣做(dd
的起源不明,但它似乎最初是作為一種訪問磁帶的工具,它有特殊的要求,並且從未被改編為通用工具)。當您檢查進度時,這會向dd
程序發送一個中斷讀取的信號。您可以選擇知道多少字節dd
將全部複製(確保不要中斷它 - 沒有進度檢查,沒有暫停),或者知道dd
到目前為止已經複製了多少字節,在這種情況下,您無法知道它將複製多少字節。
dd
GNU coreutils 中的版本(在非嵌入式 Linux 和 Cygwin 上找到)有一個標誌fullblock
,告訴在循環dd
中呼叫(和同上 for ),因此總是傳輸完整塊。錯誤資訊提示你使用它;您應該始終使用它(在輸入和輸出標誌中),除非在非常特殊的情況下(主要是在訪問磁帶時)——如果您使用它,那就是:通常有更好的解決方案(見下文)。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
.如果您需要在開頭跳過一些字節,請
tail
輸入head
: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
’s 更好),代價是管道中的附加項目(性能方面,幾乎察覺不到)。