내가 지금까지 무엇을 했는지
내 서버의 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
지난번 이후 수정되지 않았다고 가정합니다 (또는 설치되지 않은 경우에도 일부 "마지막 설치 시간" 필드가 업데이트될 수 있음).
네트워크 파일 시스템을 사용하여 대용량 파일을 전송하는 것도 좋지 않은 생각입니다.