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
このコマンドは、dd
1960年代に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