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 einとは800950+0 Datensätze ausどういう意味ですか?警告の後は+1です。エラーカウントですか?


メッセージを英語に翻訳できれば、これは答えやすいでしょう。また、「本当にランダム」を定義します。どのレベルのランダム性が必要ですか、それを何に使用しますか?
テルドン

英語のメッセージ、使用を取得するLC_ALL=Cように、コマンドの前にLC_ALL=C dd if=...
フォルカー・シーゲル

回答:


38

要約:dd正しく使用するのが難しい不気味なツールです。多数のチュートリアルがありますが、使用しないでください。dd「unix street cred」バイブが付いていますが、自分が何をしているのかを本当に理解していれば、10フィートのポールで触れてはいけないことがわかります。

dd単一の呼び出し行いread(の値によって定義されたブロックごとのシステムコールbs)。readシステムコールが指定されたバッファサイズと同じ量のデータを返すという保証はありません。これは、通常のファイルとブロックデバイスでは機能する傾向がありますが、パイプや一部のキャラクターデバイスでは機能しません。参照データをコピーするのに適したDDですいつですか?(または、read()およびwrite()partialの場合)詳細については。readシステムコールが1ブロック未満を返す場合、dd部分ブロックを転送します。指定された数のブロックがコピーされるため、転送されたバイトの合計量は要求された量よりも少なくなります。

「部分的な読み取り」に関する警告は、まさにこれを示しています。読み取りの1つが部分的であったためdd、不完全なブロックを転送しました。ブロック数で+1は、1つのブロックが部分的に読み取られたことを意味します。出力カウントはなので+0、すべてのブロックは読み取りとして書き出されました。

これは、データのランダム性には影響しません。dd書き出すバイトはすべて、読み取り元のバイトです/dev/urandom。しかし、予想よりもバイト数が少なくなりました。

Linuxは/dev/urandom任意の大規模なリクエストに対応しているため(ソース:extract_entropy_userin drivers/char/random.c)、dd通常はそこから読み取るときに安全です。ただし、大量のデータの読み取りには時間がかかります。プロセスがシグナルを受信すると、readシステムコールは戻り、出力バッファがいっぱいになります。これは正常な動作であり、アプリケーションはreadループで呼び出すことになっています。dd歴史的な理由でこれを行いません(dd'の起源は不明瞭ですが、それはテープにアクセスするためのツールとして始まったようです。テープは特殊な要件を持ち、汎用ツールとしては決して適合しませんでした)。進行状況を確認するとdd、読み取りを中断するシグナルがプロセスに送信されます。バイト数を知ることから選択できますdd合計でコピーします(中断しないようにしてください-進行状況チェック、中断なし)、またはddこれまでにコピーしたバイト数を知っている場合は、コピーするバイト数がわかりません。

ddin GNU coreutilsのバージョン(非組み込みLinuxおよびCygwinにあります)には、ループ(およびditto for )を呼び出して常に完全なブロックを転送するようにfullblock指示するフラグがあります。エラーメッセージは、使用することを示唆しています。非常に特殊な状況(主にテープにアクセスするとき)を除き、常に(入力フラグと出力フラグの両方で)使用する必要があります。使用する場合は、通常、より良い解決策があります(以下を参照)。ddreadwritedd

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

パイプライン内の追加アイテムを犠牲にしてpvdd's よりも良い)進行状況レポートを取得するために呼び出すことができます(パフォーマンスに関しては、ほとんど知覚できません)。


2
+1。これは、私が長い間StackExchangeネットワークで読んだ最もよく研​​究された投稿の1つです。簡潔でありながら、ddコマンドの詳細(歴史的および現在)をすべて含んでいますが、私は知る必要のあることに気づきませんでした。ありがとう。
宇宙のオシフラジ

4
申し訳ありませんが、ddは「正しく使用するのが難しい不格好なツール」であり、「ddを使用しないでください」というあなたの主張には同意しません。それを理解するのに時間をかけた人が正しく使用するとき、それは完全に素晴らしいユーティリティです。実際、ディスクフォレンジックツールキットはほとんどすべてddまたはdcflddなどの派生物に依存しています。
fpmurphy

1
@ fpmurphy1 GNU ddは、そのfullblockオプションのおかげで安全に使用できます。しかし、GNU coreutilsをお持ちの場合、ddあまり必要ありません。「誘導体」などdcflddされていない dd私の答えは、彼らには適用されませんので、彼らは、その設計上の欠陥に悩まされません。使用しddている大多数の人々は、それを理解するのに十分な時間を費やしておらず(せいぜい、彼らがそれを理解していると考えるのに時間をかけている)、それを使用する方法はデータ損失につながります。
ジル 'SO-悪である停止

1
@Gillesでは、誤用の可能性のある「エコー」b / cを使用するべきではありません(sudo echo hello world> / dev / sda)。
whitey04

2
@ whitey04バレルのニトログリセリンを取り扱わないことをお勧めします。マッチを使うべきではないとは言わなかった。
ジル 'SO-悪であるのをやめる'

9

この警告ddは、1回の読み取りでブロックを満たすのに十分なデータを取得できなかったときに発生します。これは、不安定または遅いデータソース、または要求されたブロックサイズよりも小さい単位でデータを書き込むソースで発生します。

データの整合性に問題はありませんが、問題は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.