dd を使用して 1 TB ディスクを 1.2 TB ディスクに複製すると、「デバイスに空き容量がありません」と表示されます。

dd を使用して 1 TB ディスクを 1.2 TB ディスクに複製すると、「デバイスに空き容量がありません」と表示されます。

dd次のコマンドを使用して、リモートxfsディスクを別の場所に複製しようとします。

ssh root@source_ip  "dd if=/dev/vda2 bs=16M conv=noerror,sync status=progress " | sudo dd of=/dev/nvme1n1 bs=16M conv=noerror,sync status=progress

ただし、次のエラー メッセージが表示されます。

828895133696 bytes (829 GB) copied, 39610.432258 s, 20.9 MB/s
1288490188800 bytes (1.3 TB) copied, 64529.849170 s, 20.0 MB/s
dd: error writing '/dev/nvme1n1': No space left on device

ソースディスクは1TB、ターゲットディスクは1.2TBです。

この場合、ディスク間のレプリケーションを実行できない理由を説明できる人はいますか?ありがとうございます!

元のディスクから削除されたファイルを回復しようとしていますが、DDがこの状況に適した唯一のツールであるかどうかはわかりません。

答え1

比較するこの回答bs=1Kここでコメントを使用):

ddオリジナルのテープデバイスで動作するように設計された古くて気まぐれなプログラムです。 1kBブロックを読み取るように指示すると、ブロックを読み取ろうとします。読み取りで1024バイト未満を返すと、それはすべてです。

conv=sync読書量が期待以下になるとdd重要になります。あなたの場合、パイプはいつでもsshチャンク16M全体をbs=16Mローカルに渡すことはできません。dd 一度に読むconv=sync「欠落している」データを0(NULバイト)で埋めます。しかし、実際のデータはありませんでした。ddローカルが次のブロックを読み取ろうとすると、ローカルが欠落していると思われるコンテンツが渡されます。

実際、ネイティブはddストリームのランダム(-ish)位置にゼロを注入します。明確でない場合は、以下を強調します。これによりデータが破損し、結果として「コピー」が事実上役に立たなくなります。

conv=noerror,syncリモート(読み取り)側での使用も間違っている可能性があります。この答えを比較してください:dd conv=sync,noerror効果は何ですか?正しく使用するには、どのように機能するかを実際に理解する必要があります。

使用しているロケールには適していませんdd conv=noerror,sync。削除または追加iflag=fullblock(サポートされている場合)正直に言うと、conv=noerror,sync iflag=fullblockパイプから読み取るときにこれらのオプションを使用しないよりも、どのような利点があるのか​​わかりません。dd

答え2

他の人がすでに指摘したように、問題はを使用していることですdd。使用規則#1はddを使用しないことですdd。使用規則#2はddあなたがすることですいいえ使用dd。使用規則#3 dd(専門家のみ)はこのbsオプションを使用しません。

そこには魔法はありませんdd。魔法がそこにあります/dev/*

ddあなたのデータを喜んで破壊しますそしてブロックサイズ設定はパフォーマンスを向上させることも、そうでない場合もあります。dd安全に使用する方法がわかっている場合にのみ使用してください。そして特定のユースケースでベンチマークを実行して、システムにそのタスクを実行させるよりも速いブロックサイズを決定しました。

ssh root@source_ip  "cat /dev/vda2" | sudo tee /dev/nvme1n1 >/dev/null

答え3

ファイルの取り消しを含む法医学に関連するすべての場合、ddこのツールは(少なくとも読むために)適切なツールです。

他の人が指摘したように、問題はsshパイプの端でブロックされた部分を読むことができないということです。したがって、2番目のddにiflag = fullblockが必要な場合、または2番目のddを完全にスキップする必要があります。

flag=noerror間違っているかもしれません。失敗したのかな?

flag=syncしばしば間違いです。 ddにオペレーティングシステムのバッファを上書きするように指示します。そうする必要はありません。せいぜいsync走る後。そして読書にとってこれは意味がありません。

2つの異なるstatus=progress項目はエラーです。どちらも互いに上書きされたと報告します。あなたは本当にそれがどのように行われたかを知りたいだけです。状態省略=...

bs=16Mよさそうですが、理想的にはbsはハードウェアブロックサイズと一致する必要があります。クラシックディスクの場合、このサイズは512バイトです。より現代的なものは4kを使用しています。 4k、16k、64kをお勧めします。

圧縮はいっぱいでないディスクにも適しています。解決策はssh -Cおそらく最も簡単です。

したがって、次のように書くことができます。

ssh -C root@source_ip  "dd if=/dev/vda2 bs=64k" | sudo dd iflag=fullblock of=/dev/nvme1n1 bs=64k

または

sudo sh -c 'ssh -C root@source_ip  "dd if=/dev/vda2 bs=64k" >/dev/nvme1n1'

(Sshに問題がある可能性があります。)
または

sudo chown `id -u` /dev/nvme1n1
ssh -C root@source_ip  "dd if=/dev/vda2 bs=64k" >/dev/nvme1n1
sudo chown root /dev/nvme1n1

またはtee

テスト

デュアルdd形式を使用するには、フル転送を実行する前に正しいオプションがあるかどうかをテストすることをお勧めします。わずかなディスク容量を占めるようにcount=100最初のエントリに追加します。dd数秒以内に2つのステータス行が表示され、同じ振替額が表示されるはずです。機能している場合は、count=100削除を繰り返してディスク全体を完了してください。

答え4

このコマンドは、dd1960年代にIBMメインフレームコマンドDDR(ディスクダンプと復元)をモデル化し、主にブロック指向I / Oをブロック指向ディスク変換および再ブロックに変換するために使用されました。しかし、ここではそうしたいのではありません。

ユースケースで重要な問題は、途中に特定のブロックサイズを読み取れない信頼できないネットワークパイプがあることです。

実際のプログラムを使用している場合dd(出力が標準互換ではないため、何を使用しているかわからない)、次のような出力を取得する必要があります。

"%u+%u records in\n", <number of whole input blocks>,
    <number of partial input blocks>

"%u+%u records out\n", <number of whole output blocks>,
    <number of partial output blocks>

ddプラス記号の前にはゼロより大きい数字だけを、プラス記号の後にはゼロより大きい数字のみを取得できるようにする必要があります。

出力パイプから読み取るときに特定の量のデータを取得する権限がないため、ssh常に取得できるよりも少ない量を読み取ろうとする必要があります。次のコマンドを使用して、ソースディスクから読み続けることができます。

dd if=/dev/xxx bs=16x1024k

問題ありません。ただし、パイプからデータを読み取り、ターゲットディスクに書き込むには、このコマンドを使用する必要があります。

dd ibs=1b obs=16x1024k of=/dev/yyy

他のオプションを使用しないでください(特に非標準オプションを使用しないでください)。ddターゲットディスクへの書き込みコマンドが書き込みで終わる場合:

nnnn+0 records in
mmmm+0 records out

成功し、dd入力から512バイト未満を読み取らなかったため、出力が正しく再ブロックされる可能性があります。

入力ブロックの一部のブロック(プラス記号の右側に> 0)が表示されたら、コピープロセスを繰り返す必要があります。

出力チャンクサイズが大きいため、もちろん、ターゲットdistに部分チャンクを書き込むこともできます。したがって、ddターゲットディスクに書き込まれる要約メッセージは、次のようになることもあります。

nnnn+0 records in
mmmm+1 records out

関連情報