Возобновление неполного образа диска с помощью dd поверх ssh

Вы можете сбросить ловушку до значения по умолчанию, задав команду ловушки -в качестве аргумента действия. Если вы сделаете это в подоболочке , это не повлияет на ловушку в родительской оболочке. В вашем скрипте вы можете сделать это для каждой команды, которую вам нужно прерывать с помощью Ctrl -C:

#!/bin/bash
# make the shell (and its children) ignore SIGINT
trap '' INT
.
.
.
# but this child won't ignore SIGINT
(trap - INT; my_program)
# the rest of the script is still ignoring SIGINT
.
.
.

0
26.12.2020, 16:32
2 ответа

Вы подтвердили, что используете загрузочный образ, поэтому исходный диск объемом 1 ТБ в настоящее время не используется. Это действительно хорошая новость.

Теперь, чтобы скопировать диск через ненадежный носитель, вам нужен либо транспортный уровень, который может автоматически -устанавливать себя (, например, OpenVPN через UDP ), либо средство для отправки перезапускаемых «фрагментов» данных.

Предположим, что все управляется с клиента и что у вас sshдоступ опосредован сертификатами/ключами, поэтому пароли не требуются.

Я предлагаю вам использовать блоки по 1 ГБ, что означает, что вам потребуется около 1000 sshподключений для передачи всего диска. Возможно, вы захотите настроить размер блока и количество в верхней части скрипта. В разделе «Действительные данные» вы можете выбрать запись 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

Результирующий образ будет не меньше размера исходного диска; дополнительных нулевых байтов будет достаточно для округления до следующего полного размера фрагмента. Вы можете использовать truncate, чтобы уменьшить размер результирующего несжатого изображения, если это важно.

1
18.03.2021, 22:40

Боюсь, чтобы отправить недостающий бит, вам все равно придется повторно сжимать с самого начала, даже если вы передаете только недостающие биты, поскольку поток сжатия, такой как поток 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не был изменен (и даже не смонтирован, что может обновить некоторое поле «время последнего монтирования», например )с последнего раза.

Также не рекомендуется использовать сетевую файловую систему для передачи больших файлов.

1
18.03.2021, 22:40

Теги

Похожие вопросы