今まで何をしたのか
私のサーバーのHDDパーティションのディスクイメージを作成し、それを自分のデスクトップ(クライアント)にコピーしたいと思います。サーバーで次のコマンドを使用しました。
dd if=/dev/md3 status=progress bs=500k | bzip2 --best > /mnt/client/image.bz2
/mnt/client/
私のクライアントのsshfsのインストール場所はどこですか?
残念ながら、私のクライアントは固定IPアドレスを持っておらず、ディスクイメージは予想以上に時間がかかります。 511GB(1TB)では、ISPは新しいIPアドレスを使用するよう強制し、両方のSSH接続が失われました。これをssh接続dd ... | bzip2 > ...
とsshfsマウントと呼びます。
ディスクイメージを作成する必要があることに注意してください。ファイルをコピーするだけでは十分ではありません。また、ディスクイメージを保存するためのサーバー容量が不足しているため、クライアントに直接保存する必要があります。
私の質問
ディスクイメージを復元する方法は?
以前にコピーしたデータが再送信されないように追加の画像を復元する方法は?特に、既に送信されたデータは圧縮されたアーカイブ内にあるため、さらにそうです。
ネットワーク接続の帯域幅がボトルネックを引き起こすように、圧縮を維持する方が良い選択肢です。しかし、仕事が簡単になれば、必ずしも必要ではありません。
ファイルについても同様のことを考えましたが、rsync
ここには適用されません。
コピーした(部分的な)アーカイブを解凍し、サイズをバイト単位で測定し、次のようなものを使用したいと思います。
dd if=/dev/md3 skip=[size of uncompressed partial image] iflag=skip_bytes
しかし、既存のアーカイブにデータストリームを追加する方法はわかりません。>>
アーカイブに追加を使用するだけでは機能しない可能性があると思います。そして、アーカイブを解凍するのに時間がかかる場合があります。しかし、画像の一部の圧縮されていないサイズを取得する方法がわかりません。
私は完全な圧縮操作をあきらめているとしましょう。少なくともdd if=... skip=... >> /mnt/client/uncompressed_image
期待通りに動作しますか?
SSHを使用するときに「接続セキュリティ」を維持する方法は?
非静的IPアドレスがSSH接続を失っていないことをどのように確認できますか?それとも、少なくともddコマンドが中断された場合に簡単に再起動できるようにするにはどうすればよいですか?
振り返ってみると、私の顧客から次のことを行うのが賢明だったかもしれません。
ssh root@server "dd if=/dev/md3 | bzip2 --best -c" | dd of=image.bz2
これにより、sshfsマウントにクライアントのIPが不要になります。しかし、私のIPアドレスが変わると、まだsshパイプが壊れます。だからこれだけでは何も解決しません。
答え1
リカバリイメージが使用中であることが確認され、現在1TBソースディスクは使用されていません。本当に良いニュースですね。
信頼できないメディアを介してディスクをコピーするには、自動的にリセットできるトランスポート層(UDPベースのOpenVPNなど)または再起動可能なデータ「チャンク」を送信する方法が必要です。
私たちはすべてがクライアントによって制御され、ssh
証明書/キーを介してアクセスできるため、パスワードは必要ないと仮定します。
1GBブロックを使用することをお勧めします。これはssh
、ディスク全体を転送するために約1000の接続が必要であることを意味します。スクリプトの上部付近でブロックサイズと数を調整する必要があるかもしれません。 「有効なデータ」セクションでは、bzip2
圧縮ブロックまたは非圧縮一般ブロックを書き込むことを選択できます。 (bzip2
複数の圧縮ブロックを処理できるため問題ありません。)
#!/bin/bash
#
dev=/dev/sda1 # Device to read
img=image.dat # Target image filename
bs=32M # dd blocksize per read
count=32 # Number of blocks per ssh chunk
for (( chunk=0; ; ))
do
# Grab chunk from server
#
ssh -zn root@remoteServer "
dev=$dev chunk=$chunk bs=$bs count=$count "'
echo "chunk $chunk from device $dev"
{
dd bs=$bs skip=$((chunk*count)) count=$count if=$dev 2>/tmp/dd.$$
echo $? >/tmp/ss.$$
dd bs=$bs iflag=fullblock count=$count if=/dev/zero 2>/dev/null
} | dd bs=$bs iflag=fullblock count=$count 2>/dev/null
echo "========"
echo "status $(cat /tmp/ss.$$)"
cat /tmp/dd.$$
rm -f /tmp/dd.$$ /tmp/ss.$$
' |
{
# Extract data from chunk
#
IFS= read -r info
echo "Received: $info"
dd bs=$bs iflag=fullblock count=$count of=/var/tmp/data.$$
cat >/var/tmp/meta.$$
}
# Append extracted data
#
meta=$(cat /var/tmp/meta.$$)
echo "Meta:"
echo "$meta" | sed 's/^/| /'
if [[ "$meta" =~ ([[:digit:]]+)\+[[:digit:]]+' records in' ]]
then
# Valid data
#
# bzip2 </var/tmp/data.$$ >> "$img.bz2"
dd bs=$bs count=$count seek=$((chunk*count)) conv=notrunc if=/var/tmp/data.$$ of="$img"
# Is this all
#
if [[ "${BASH_REMATCH[1]}" -lt $count ]]
then
# We are done
#
break
fi
# Next round the loop
#
((chunk++))
else
echo "Invalid data received for chunk $chunk; retrying"
fi
done
# Tidy up
#
rm -f /var/tmp/data.$$ /var/tmp/meta.$$
exit 0
結果のイメージは、少なくともソースディスクのサイズです。追加の0バイトは、次のブロックサイズ全体に丸めるのに十分です。これが重要な場合は、truncate
圧縮されていない結果の画像のサイズを縮小できます。
答え2
不足しているビットを送信するには、不足しているビットを圧縮されたストリーム(以前に説明したようにbzip2など)に送信する場合でも、最初から再圧縮する必要があります。
$s
送信されたコンテンツのサイズが含まれている場合
dd if=/dev/md3 status=progress bs=500k | bzip2 --best | {
head -c "$s" > /dev/null
ssh host 'cat >> /mnt/client/image.bz2'
}
(head
GNUのような実装がhead
ここで必要以上のものを読まないと仮定します)。
またはその逆も:
ssh other-host "
dd if=/dev/md3 status=progress bs=500k | bzip2 --best |
tail -c +$(($s + 1))" >> /mnt/client/image.bz2
/dev/md3
前回以降は変更されていないとします(またはインストールされていない場合でも、一部の「最後のインストール時間」フィールドが更新される可能性があります)。
ネットワークファイルシステムを使用して大容量ファイルを転送するのも悪い考えです。