Um Raspberry Pi pode ser usado para criar um backup de si mesmo?

78

Esta pergunta responde à pergunta de como eu uso um computador externo para criar um backup do meu RPi.

Gostaria de saber se posso criar uma imagem de backup do cartão SD atualmente em uso e copiá-la para um arquivo em um dispositivo de armazenamento USB. Isso é possível? Caso contrário, existe alguma maneira de criar um backup de uma RPi sem envolver outro computador?

Eric Wilson
fonte
2
Claro, mas pule / tmp, / run, / proc, / sys, / dev e / mnt. Você não precisa criar uma imagem, precisa de um backup para criar ou atualizar uma imagem. Portanto, não use dd, investigue rsync.
goldilocks
1
@goldilocks Eu adoraria se você colocasse esse comentário em uma resposta mais completa, explicando o processo de backup e restauração que você tem em mente.
Eric Wilson
Concluído - desculpe-me por alguns dias para encontrar o tempo.
goldilocks
1
Se o seu volume de destino for grande o suficiente, remontar o sistema de arquivos somente leitura e fazer uma ddcópia com um tamanho de bloco apropriado provavelmente será mais rápido para uma cópia "nova". Fazer uma cópia de arquivo por arquivo em mídia flash / SD provavelmente é uma má idéia.
Chris Stratton

Respostas:

86

Aqui está uma introdução ao uso rsyncpara backup no Pi. Depois que o backup inicial é criado, mantê-lo atualizado dessa maneira é muito mais rápido do que rasgar constantemente a imagem inteira. Você pode fazer isso em um disco rígido local ou em uma rede.

Na verdade, você não deseja uma cópia completa de um sistema em execução como backup, pois algumas das coisas ostensivamente existentes no sistema de arquivos existem apenas em tempo de execução. Incluir isso em um backup e usá-lo para recriar uma imagem posteriormente pode criar problemas para você.

Existem outras exceções também. rsyncpode aceitar uma lista de padrões ( glob ) a serem excluídos e esses podem ser lidos a partir de um arquivo, então vamos primeiro examinar o que deveria estar nesse arquivo. Observe que as entradas são do formato /directory/*e não /directory. Isso ocorre porque queremos que eles existam, mas não queremos copiar nada neles.

/proc/*
/sys/*

Eles realmente não existem no disco. Eles são uma interface para o kernel, que os cria e mantém na memória . Se você copiá-los e depois copiá-los de volta para um sistema e inicializá-lo, será (na melhor das hipóteses) sem sentido, pois o kernel os usa como pontos de montagem para as interfaces. em um diretório com dados, tente. Funciona e não causa nenhum dano, mas as coisas que estavam no diretório agora estão inacessíveis.]

Observe que é essencial que os pontos de montagem /syse /procexistam. Mas eles não devem conter nada. Próximo:

/dev/*

O devdiretório não é exatamente a mesma coisa que proce, sysmas para nossos propósitos, é. Se você acredita que deve salvar isso para poder ter os mesmos nós de dispositivo em seu backup ou algo assim, está errado . Não se incomode. Não copie dev. Há muito tempo, o Linux funcionava dessa maneira, mas não funciona mais.

/boot/*

Esse é um caso especial com a maioria (talvez todas) das distros específicas do Pi, como o Raspbian. Na verdade, é um ponto de montagem para a primeira partição vfat. Nós vamos lidar com isso separadamente. Faça o que fizer, não se preocupe em incluí-lo aqui, porque, novamente, é um ponto de montagem.

/tmp/*
/run/*

/rungeralmente também não está no disco, está na memória. Talvez /tmppossa ser muito (isso economizaria um pouco de ação do cartão SD), mas, em qualquer caso, como os nomes sugerem, esses não são locais para armazenar dados persistentes. Os aplicativos que os utilizam esperam que sejam excluídos a cada inicialização.

/mnt/*
/media/*

Isso é importante principalmente se você planeja fazer backup em um disco rígido ou pendrive e o dispositivo está dentro /mntou /media(a montagem automática tende a usar o último), porque se você não excluir a localização desses dispositivos no sistema de arquivos, crie um loop fazendo backup do conteúdo da unidade para si mesma, até que fique sem espaço. Eu acho que rsync pode ser inteligente o suficiente para identificar algo tão estúpido, mas tente evitar testar a premissa.

Para o backup real: Crie um diretório para fazer backup no disco rígido montado localmente, no dispositivo USB etc. - por exemplo, "pi_backup". Você pode alternativamente fazer backup em um local remoto via ssh(veja abaixo) ou usando um sistema de arquivos montado em rede, mas isso provavelmente levará um tempo na primeira vez.

Se o arquivo que contém a lista a excluir for /rsync-exclude.txt1 e sua unidade for /mnt/usbhd, faça o backup real:

rsync -aHv --delete --exclude-from=/rsync-exclude.txt / /mnt/usbhd/pi_backup/

Observe que há uma barra finalpi_backup/ .

Isso levará um tempo e produzirá muita saída (se você quiser examinar isso em um log, acrescente > rsync.log). --deletenão faz sentido na primeira vez, mas para manter o backup atualizado, use-o. Isso garante que as coisas que você excluiu posteriormente no Pi também sejam removidas do seu backup. Os aconjuntos recursão em diretórios e garante que todos os atributos do arquivo correspondam. -Hé preservar os links físicos 2 , vé detalhado, e é por isso que você obtém alguma saída (caso contrário, rsyncé silencioso). Veja man rsyncpara mais.

Há um atalho pelo qual você pode pular o --exclude-fromarquivo. Se você tem certeza de que todas as coisas que não deseja copiar ( /tmpetc.) estão em sistemas de arquivos separados, basta usar:

rsync -axHv --delete-during / /mnt/usbhd/pi_backup/

-xfoi inserido. Esta é a forma abreviada de --one-file-system, que indica rsyncpara não ultrapassar os limites do sistema de arquivos. Pessoalmente, prefiro o --exclude-from, mas, por exemplo, o Raspbian padrão, --one-file-systemfuncionará bem. Você pode usar os dois se quiser ter -xcuidado: D

Esse não é um backup completo. É o suficiente se você não colocou nada boote não tem problema em usar o backup para restaurar o sistema colocando o cartão em um computador e executando:

rsync -av --delete-during /mnt/usbhd/pi_backup/ /mnt/sdcard_partition2/

Você também pode fazer isso com um cartão com uma nova imagem (presumindo que seja a mesma da sua imagem base), embora isso seja um pouco ineficiente se você precisar criar a imagem (porque você substituirá a maior parte dela). Você também pode conectar outro cartão SD através de um adaptador USB com essa imagem e usar o método acima para manter um cartão duplicado.

Se você colocou coisas /boot(por exemplo, um kernel personalizado), inclusive /boot/config.txt, também será necessário fazer o backup (bastante simples - não há muito). Faça-o separadamente e, quando você restaurar, esse material será colocado na primeira partição.

Veja aqui se você deseja criar uma imagem em branco do estilo Raspbian na qual possa fazer backup. Você pode usar uma metodologia semelhante para criar uma placa de estilo Raspbian vazia - ao invés de lidar com um .imgarquivo, você estaria lidando com um dispositivo real (por exemplo /dev/sdb), o que significa que tudo o que você precisa fazer é criar a tabela de partição fdiske, em seguida, formato /dev/sdb1e sdb2(ou o que for) com mkfs.

Mas copiar toda a imagem é mais fácil! Por que se preocupar com isso?

Não é tão difícil; Eu restaurei para um cartão em branco (formatado de acordo com o último link) em 10 minutos. Sim, apenas usar ddtudo é mais simples (se você achar coisas como palavras confusas ...), MAS leva um bom tempo toda vez que você deseja atualizar seu backup, porque você deve fazer 100% dele sempre. Usando rsync, uma vez que um backup existe, atualizá-lo é muito, muito mais rápido, para que você possa configurar isso para acontecer sem problemas todos os dias via cron. Em uma rede mesmo. A cada seis horas. Quanto mais você faz isso, menos tempo levará.

rsync através da ssh

Aqui está um exemplo:

rsync [options] --rsh="ssh [ssh options]" root@[the pi ip]:/ /backup/rpi/

"Opções" seria, por exemplo, -av --delete --exclude-from=/rsync-exclude.txte "ssh options" é o que você normalmente usa (se houver). Você deve ter acesso root via sshpara fazer isso, para efeitos de um backup do sistema (definido PermitRootLogin=yesem /etc/ssh/sshd_confige reinicie o servidor).


1 Você deve manter este arquivo. Você pode colocar comentários nas linhas que começam com #ou ;. Isso pode incluir o rsynccomando real , que pode ser copiado e colado posteriormente, para que você não precise se lembrar sempre.

2 Obrigado a Kris por apontar rsyncnão faz isso automaticamente.

Cachinhos Dourados
fonte
Cachinhos Dourados. Parece um ótimo uso do rysync. Alguma chance de transformá-lo em um script para nós?
totalitário
Em vez de excluir manualmente todos os pontos de montagem, por que não mkdir /tmp/backupable && mount --bind / /tmp/backupablee rsync isso? Isso também tem a vantagem de fazer backup de todos os dados armazenados em locais "sombreados" por algo montado lá.
n.st 18/12/14
@ n.st Boa ideia (lol)! Editei a sugestão na pergunta, embora ainda ache que usar --exclude-fromé uma ideia melhor. Se tiver tempo, você pode escrever isso como uma resposta separada, você tem o meu voto e eu posso fazer referência a isso. Essa resposta é longa demais.
goldilocks
1
@IgorGanapolsky A intenção é não criar uma imagem (leia a parte "Mas copiar toda a imagem é mais fácil! Por que se preocupar com isso?" ). Além de ser mais fácil e rápido de manter uma vez criado, esse método geralmente é mais flexível. Se você quiser usá-lo mais tarde para criar um, .imgvocê pode; isso e isso deve ajudar a explicar como eles são estruturados e podem ser criados.
goldilocks
1
Veja o parágrafo que começa, "Esse não é um backup completo ..." . É basicamente a mesma coisa ao contrário. Isso pode ajudar com alguns conceitos pelos quais as pessoas geralmente confundem.
goldilocks
24

Um script de trabalho da comunidade Raspberry feito por um membro lá.

Você pode reutilizar e ajustar o código como desejar. É bem documentado e auto-explicativo.

#!/bin/bash

# Setting up directories
SUBDIR=raspberrypi_backups
DIR=/hdd/$SUBDIR

echo "Starting RaspberryPI backup process!"

# First check if pv package is installed, if not, install it first
PACKAGESTATUS=`dpkg -s pv | grep Status`;

if [[ $PACKAGESTATUS == S* ]]
   then
      echo "Package 'pv' is installed."
   else
      echo "Package 'pv' is NOT installed."
      echo "Installing package 'pv'. Please wait..."
      apt-get -y install pv
fi

# Check if backup directory exists
if [ ! -d "$DIR" ];
   then
      echo "Backup directory $DIR doesn't exist, creating it now!"
      mkdir $DIR
fi

# Create a filename with datestamp for our current backup (without .img suffix)
OFILE="$DIR/backup_$(date +%Y%m%d_%H%M%S)"

# Create final filename, with suffix
OFILEFINAL=$OFILE.img

# First sync disks
sync; sync

# Shut down some services before starting backup process
echo "Stopping some services before backup."
service apache2 stop
service mysql stop
service cron stop

# Begin the backup process, should take about 1 hour from 8Gb SD card to HDD
echo "Backing up SD card to USB HDD."
echo "This will take some time depending on your SD card size and read performance. Please wait..."
SDSIZE=`blockdev --getsize64 /dev/mmcblk0`;
pv -tpreb /dev/mmcblk0 -s $SDSIZE | dd of=$OFILE bs=1M conv=sync,noerror iflag=fullblock

# Wait for DD to finish and catch result
RESULT=$?

# Start services again that where shutdown before backup process
echo "Start the stopped services again."
service apache2 start
service mysql start
service cron start

# If command has completed successfully, delete previous backups and exit
if [ $RESULT = 0 ];
   then
      echo "Successful backup, previous backup files will be deleted."
      rm -f $DIR/backup_*.tar.gz
      mv $OFILE $OFILEFINAL
      echo "Backup is being tarred. Please wait..."
      tar zcf $OFILEFINAL.tar.gz $OFILEFINAL
      rm -rf $OFILEFINAL
      echo "RaspberryPI backup process completed! FILE: $OFILEFINAL.tar.gz"
      exit 0
# Else remove attempted backup file
   else
      echo "Backup failed! Previous backup files untouched."
      echo "Please check there is sufficient space on the HDD."
      rm -f $OFILE
      echo "RaspberryPI backup process failed!"
      exit 1
fi

Considere adicionar comentários ao fórum original ou publique sua própria versão para ajudar a amadurecer o conteúdo. Tome um pouco, dê um pouco.

* E obrigado por devolver o AndersW (clique no script GIT)

Piotr Kula
fonte
2
E se o sistema de arquivos (exclusão de arquivos, novos arquivos adicionados) mudarem durante o tempo em que o pi estiver fazendo backup?
31513 Keiki
2
Eu faço backup de vários discos enquanto eles estão em execução com o rsync, e frequentemente consegui exatamente o que preciso desses backups de arquivos. No entanto, em geral, um sistema de arquivos unix não pode ser copiado perfeitamente (com todos os bits no lugar e corretos) enquanto o sistema de arquivos está montado (*). Uma cópia feita enquanto o sistema foi montado às vezes é chamada de "cópia suja". Várias medidas podem ser tomadas para melhorar a qualidade de uma cópia suja (como o script acima faz, desligando o cron e o mysql), mas não pode ser perfeito. Felicidades! * - Eu estou errado sobre isso, depende do sistema de arquivos.
Tai Viinikka
1
Você pode olhar para os utilitários de backup recomendados pela Debian e ver se o Pi tem uma porta deles. rsnapshotsoa promissor
Piotr Kula
1
@TaiViinikka Você não precisa de uma cópia perfeita. Você precisa de uma cópia parcial que possa ser (rápida e facilmente) reimposta na imagem base original. rsyncé o caminho a percorrer; quando tiver tempo amanhã, adicionarei uma resposta. rsnapshottambém vale a pena investigar.
goldilocks
3
Com base na resposta ppumkins acima, sincronizei o script 'dd' com os comentários mais recentes no segmento original e adicionei algumas pequenas melhorias. O resultado final está disponível aqui: < github.com/aweijnitz/pi_backup >. Por favor, não hesite em adicionar melhorias e me enviar solicitações pull.
precisa saber é o seguinte
14

Adaptei a resposta @goldilocks no rsync para fazer backup no pi. Eu faço backup em uma ext4partição em um disco rígido montado no Pi. Se o HDD não estiver montado, o rsync copiará para o diretório de montagem (até o cartão SD estar cheio). Se o HDD não estiver montado no rwmodo, serão produzidas copiosas mensagens de erro. Nenhuma dessas opções é desejável, portanto, verifico se minha partição está montada no rwmodo antes de prosseguir.

OBSERVAÇÃO 2015-03-03 Modifiquei minha resposta para copiar com precisão os hardlinks. O original funcionou, mas converteu muitos hardlinks em arquivos. Além de desperdiçar espaço, isso compromete muitos usos que pressupõem que os hardlinks estão no lugar. (Minha imagem atual possui 869 links, muitos deles em Raspbian.)

Meu script para fazer isso segue. (Minha partição está PiDatamontada em/mnt/PiData

#!/bin/bash
# script to synchronise Pi files to backup
BACKUP_MOUNTED=$(mount | awk '/PiData/ {print $6}' | grep "rw")
if [ $BACKUP_MOUNTED ]; then
    echo $BACKUP_MOUNTED
    echo "Commencing Backup"
    rsync -avH --delete-during --delete-excluded --exclude-from=/usr/bin/rsync-exclude.txt / /mnt/PiData/PiBackup/
else
    echo "Backup drive not available or not writable"
fi

Restaure (ou atualize outro Pi) com o seguinte: -

sudo rsync -avH /mnt/PiData/PiBackup/ /

Eu aprimorei o rsync-exclude.txtpara eliminar arquivos desnecessários.

O primeiro grupo são os diretórios documentados por @goldilocks https://raspberrypi.stackexchange.com/users/5538/

O segundo grupo são os arquivos e diretórios criados pelo OS X quando eu acesso o meu Pi usando o AFP (Apple Filing Protocol). (Normalmente, eles são invisíveis no OS X, mas não no Raspbian. De qualquer forma, não há necessidade de fazer backup.) Mesmo que você nunca use o AFP, isso não causará danos.

O terceiro grupo são arquivos que não precisam de backup (e certamente não são copiados para outro Pi). Exemplos fake-hwclock.data, relatórios do RPi-Monitor. Você provavelmente terá outros.

/proc/*
/sys/*
/dev/*
/boot/*
/tmp/*
/run/*
/mnt/*

.Trashes
._.Trashes
.fseventsd
.Spotlight-V100
.DS_Store
.AppleDesktop
.AppleDB
Network Trash Folder
Temporary Items

.bash_history
/etc/fake-hwclock.data
/var/lib/rpimonitor/stat/
Milliways
fonte
1
Existe uma maneira de tornar essa saída um arquivo .img ?
IgorGanapolsky
@IgorGanapolsky Bem, como todos os arquivos essenciais estão lá (exceto os arquivos de inicialização), é obviamente possível, mas se você quiser uma imagem, faça uma imagem. Você deve fazer qualquer nova pergunta em uma nova postagem, não comentários.
Milliways
@ Milliways, por que não devemos usar "sudo rsync ..."? Existem alguns arquivos que podem não ser sincronizados?
Smilia 4/11
6

Eu tenho três Pis em execução na minha rede local e preciso fazer backup deles regularmente com o cron quando eles estiverem funcionando. Por isso, criei um script capaz de criar backups de dd, tar e rsync e restaurá-los. Eu prefiro usar o rsync para meus backups, mas outras pessoas preferem dd ou tar. Já é usado por muitas pessoas. Espero que seja útil para outros também :-) raspibackup - Raspberry cria backups de si mesmo

framp
fonte
1
Não, desculpe: pedir ao usuário para executar (como root!) Um script baixado por HTTP é irresponsável. Distribua esse script por um canal seguro.
Clément
1
Eu não acho que esteja fora do assunto, e a raiz ou não não importa muito. O ponto é que o software deve ser distribuído por um canal seguro, e sua resposta está incentivando más práticas de segurança.
Clément
1
Isso seria um grande passo em frente, sim :)
Clément
2
Apenas observe que a entrega por HTTPS não adiciona nenhuma segurança nesta instância! Você ainda está baixando e executando um script da Internet. O processo seguro é fazer o download do script (http / https é irrelevante), abra o script em um editor e leia-o de cima para baixo, verifique se há esquisitices e inseguranças. Somente quando estiver satisfeito, você deve executá-lo. Framp pode ser um hacker para todos qualquer um de nós sabe e entrega sobre https só iria fazê-lo sorrir nesse caso :) (BTW, que não é uma acusação Framp!)
Julian Knight
2
Eu concordo com você. É por isso que existem duas maneiras descrito como instalar o script: 1. Use o installerScript 2. baixá-lo manualmente, verifique o código e, em seguida, instalá-lo manualmente
framp
3

Aqui está nossa ferramenta estável para esses fins: https://github.com/aktos-io/aktos-dcs-tools

Esta ferramenta é escrito para make sshconexões, make backup-root, make mount-roota partir de locais remotos em mente no início, e, em seguida, são adicionados sessões locais. Portanto, ele suporta backups locais, backups remotos diretos, backups remotos por proxy. Os backups são feitos de forma incremental (apenas as diferenças são transferidas) e os diretórios de backup são independentes (basta escolher um diretório / versão para restaurar, qualquer diretório possui um backup completo). Obviamente, você tem versões (backup.last-0 é a mais recente). Você pode interromper o processo de backup a qualquer momento e continuar mais tarde.

Aqui estão as instruções para o seu problema específico:

 ssh to-your-raspberry
 cd /mnt/usb0/my-rpi-backups
 git clone https://github.com/ceremcem/aktos-dcs-tools backup-tools
 ln -s backup-tools/Makefile .

 ./backup-tools/configure # you do not need to make any settings for local sessions, just save the default 

 # just for the first time
 make set-local-session  # a flag file is created
 make init               # snapshots directory is created

 # anytime you want to back up
 make backup-root        # backup with rsync

EDITAR

Agora há um novo destino adicionado: você pode criar um cartão SD físico a partir dos seus backups com um comando:

make create-disk-from-last-backup

Siga as instruções, crie seu cartão SD, inicie o RaspberryPi com este cartão SD recém-criado.

ceremcem
fonte
1

Aqui está uma abordagem completamente diferente. Você pode usar LVM ( L ogical V olume M anager) para fazer backups consistentes. Além de outras melhorias, como fácil adição, expansão e redução de armazenamento ou restauração do sistema operacional para um status anterior a partir de um instantâneo, você também pode fazer backups. Você não precisa se preocupar com arquivos dinâmicos alterados durante o backup, configurando sistemas de arquivos somente leitura, excluindo diretórios específicos ou qualquer outra coisa. Com o LVM, você simplesmente cria um instantâneo, monta esse instantâneo e faz backup com o método que preferir. Você pode copiar cp -a, espelhar rsync, arquivar tarou criar uma imagem comdd. Supondo que você montou um dispositivo de backup, /mnt/usbhd/pi_backup/você pode fazer, por exemplo:

rpi ~$ sudo lvcreate --snapshot --name rpi_snap --size 1G rpi_vg/root_lv
rpi ~$ sudo mkdir /mnt/snapshot
rpi ~$ sudo mount /dev/mapper/rpi_vg-rpi_snap /mnt/snapshot

# make backups
rpi ~$ sudo cp -a /mnt/snapshot/ /mnt/usbhd/pi_backup/
rpi ~$ sudo rsync -aH --delete /mnt/snapshot/ /mnt/usbhd/pi_backup/
rpi ~$ sudo tar -czf /mnt/usbhd/pi_backup/backup.tar.gz -V "Backup of my Raspberry Pi" -C /mnt/snapshot/ ./
rpi ~$ sudo dd if=/mnt/snapshot/ of=/mnt/usbhd/pi_backup/backup.img bs=4M

rpi ~$ sudo umount /mnt/snapshot/
rpi ~$ sudo lvremove rpi_vg/rpi_snap

Leva apenas uma vez um pouco de esforço para configurar o LVM . Como fazer isso, você pode ver os backups e as capturas instantâneas fáceis de um sistema em execução com o LVM .

Ingo
fonte
0

Encontrei uma ferramenta de backup que cria imagens instaláveis.

Ele também possui utilitários para montar e reduzir imagens.

Isso pode ser útil para outras pessoas

A documentação que acompanha é muito breve, portanto, observe o seguinte: -

  1. Extraia os utilitários para qualquer diretório e torne os scripts executáveis.
  2. Monte uma ext4partição formatada no seu Pi em /mntou /media(qualquer formato que permita arquivos grandes e seja suportado pelo Pi, por exemplo, exFAT ou uma unidade de rede pode ser usado).
  3. Para a execução inicial, você será solicitado a fornecer um nome de Imagem de backup, por exemplo /mnt/Image/BusterBackup.img
  4. Você será solicitado a fornecer um tamanho de sistema de arquivos Image ROOT (em MB); este pode ser 0 para o menor tamanho possível ou em branco para backup completo.
  5. Nas execuções subsequentes, insira o caminho da imagem de backup para atualização incremental.
An example of the commands I used:-
# Mount USB
sudo mount /dev/sda1 /mnt/Image/
# Update backup
sudo image-utils/image-backup /mnt/Image/BusterBackup.img
# Mount backup
sudo image-utils/image-mount /mnt/Image/BusterBackup.img  MountedImages
When done, run:
sudo umount MountedImages; sudo losetup -d /dev/loop0
# Compress backup
sudo sh -c "gzip -9c /mnt/Image/BusterBackup.img  > Images/BusterBackup.img.gz"

Modifiquei levemente o original (para copiar pontos de montagem), para calcular corretamente os desvios e tamanhos das partições e adicionei alguns comentários.

#!/bin/bash
# Original https://raspberrypi.org/forums/viewtopic.php?p=1528736
# 2019-09-26    Modified to set size of boot sector

trap '{ stty sane; echo ""; errexit "Aborted"; }' SIGINT SIGTERM

ADDBLK=0

# Set BOOT_SIZE_MB to the Desired boot sector size (in MB) - should be multiple of 4MB
BOOT_SIZE_MB=256
BOOTSIZEM=$BOOT_SIZE_MB'M'

BOOTBEG=8192
BOOT_SIZE="$((BOOT_SIZE_MB * 1024 * 1024))"
ROUND_SIZE="$((4 * 1024 * 1024))"
# Ensure root sector starts on an Erase Block Boundary (4MB)
ROOTBEG=$(((BOOT_SIZE + ROUND_SIZE -1) / ROUND_SIZE * ROUND_SIZE / 512 + BOOTBEG))

MNTPATH="/tmp/img-backup-mnt"

ONEMB=$((1024 * 1024))

# create BOOT loop device
mkloop1()
{
  local INFO1=""
  local SIZE1=0
  local START1=0

  sync
  INFO1="$(sfdisk -d "${IMGFILE}")"
  START1=$(grep type=c <<< "${INFO1}" | sed -n 's|^.*start=\s\+\([0-9]\+\).*$|\1|p')
  SIZE1=$(grep type=c <<< "${INFO1}" | sed -n 's|^.*size=\s\+\([0-9]\+\).*$|\1|p')
  LOOP1="$(losetup -f --show -o $((${START1} * 512)) --sizelimit $((${SIZE1} * 512)) "${IMGFILE}")"
  if [ $? -ne 0 ]; then
    errexit "Unable to create BOOT loop device"
  fi
}

rmloop1()
{
  if [ "${LOOP1}" != "" ]; then
    sync
    losetup -d "${LOOP1}"
    LOOP1=""
 fi
}

# create ROOT loop device
mkloop2()
{
  local INFO2=""
  local SIZE2=0
  local START2=0

  sync
  INFO2="$(sfdisk -d "${IMGFILE}")"
  START2=$(grep type=83 <<< "${INFO2}" | sed -n 's|^.*start=\s\+\([0-9]\+\).*$|\1|p')
  SIZE2=$(grep type=83 <<< "${INFO2}" | sed -n 's|^.*size=\s\+\([0-9]\+\).*$|\1|p')
  LOOP2="$(losetup -f --show -o $((${START2} * 512)) --sizelimit $((${SIZE2} * 512)) "${IMGFILE}")"
  if [ $? -ne 0 ]; then
    errexit "Unable to create ROOT loop device"
  fi
}

rmloop2()
{
  if [ "${LOOP2}" != "" ]; then
    sync
    losetup -d "${LOOP2}"
    LOOP2=""
  fi
}

# Mount Image partitions
mntimg()
{
  MNTED=TRUE
  if [ ! -d "${MNTPATH}/" ]; then
    mkdir "${MNTPATH}/"
    if [ $? -ne 0 ]; then
      errexit "Unable to make ROOT partition mount point"
    fi
  fi
  mkloop2
  mount "${LOOP2}" "${MNTPATH}/"
  if [ $? -ne 0 ]; then
    errexit "Unable to mount image ROOT partition"
  fi
  if [ ! -d "${MNTPATH}/boot/" ]; then
    mkdir -p "${MNTPATH}/boot/"
    if [ $? -ne 0 ]; then
      errexit "Unable to make BOOT partition mount point"
    fi
  fi
  mkloop1
  mount "${LOOP1}" "${MNTPATH}/boot/"
  if [ $? -ne 0 ]; then
    errexit "Unable to mount image BOOT partition"
  fi
}

umntimg()
{
  umount "${MNTPATH}/boot/"
  if [ $? -ne 0 ]; then
    errexit "Unable to unmount image BOOT partition"
  fi
  rmloop1
  umount "${MNTPATH}/"
  if [ $? -ne 0 ]; then
    errexit "Unable to unmount image ROOT partition"
  fi
  rmloop2
  rm -r "${MNTPATH}/"
  MNTED=FALSE
}

errexit()
{
  echo ""
  echo "$1"
  echo ""
  if [ "${MNTED}" = "TRUE" ]; then
    umount "${MNTPATH}/boot/" &> /dev/null
    umount "${MNTPATH}/" &> /dev/null
    rm -rf "${MNTPATH}/" &> /dev/null
  fi
  rmloop1
  rmloop2
  exit 1
}

LOOP1=""
LOOP2=""
MNTED=FALSE

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

if [ $(id -u) -ne 0 ]; then
  errexit "$0 must be run as root user"
fi

PGMNAME="$(basename $0)"
for PID in $(pidof -x -o %PPID "${PGMNAME}"); do
  if [ ${PID} -ne $$ ]; then
    errexit "${PGMNAME} is already running"
  fi
done

rsync --version &> /dev/null
if [ $? -ne 0 ]; then
  errexit "rsync not installed (run: apt-get install rsync)"
fi

if command -v systemctl > /dev/null && systemctl | grep -q '\-\.mount'; then
  SYSTEMD=1
elif [ -f /etc/init.d/cron ] && [ ! -h /etc/init.d/cron ]; then
  SYSTEMD=0
else
  errexit "Unrecognized init system"
fi

if [ ${SYSTEMD} -eq 1 ]; then
  ROOT_PART="$(mount | sed -n 's|^/dev/\(.*\) on / .*|\1|p')"
else
  if [ ! -h /dev/root ]; then
    errexit "/dev/root does not exist or is not a symlink"
  fi
  ROOT_PART="$(readlink /dev/root)"
fi

ROOT_TYPE=$(blkid "/dev/${ROOT_PART}" | sed -n 's|^.*TYPE="\(\S\+\)".*|\1|p')

ROOT_DEV="${ROOT_PART:0:(${#ROOT_PART} - 1)}"
if [ "${ROOT_DEV}" = "mmcblk0p" ]; then
  ROOT_DEV="${ROOT_DEV:0:(${#ROOT_DEV} - 1)}"
fi

PTUUID="$(blkid "/dev/${ROOT_DEV}" | sed -n 's|^.*PTUUID="\(\S\+\)".*|\1|p')"

DEVSIZE=$(blockdev --getsize64 "/dev/${ROOT_PART}")
BLKSIZE=$(blockdev --getbsz "/dev/${ROOT_PART}")
BLKCNT=$((${DEVSIZE} / ${BLKSIZE}))
INFO="$(df | grep /dev/root)"
DFKSIZE=$(awk '{print $2}' <<< "${INFO}")
DFKFREE=$(awk '{print $4}' <<< "${INFO}")
ROOTSIZE=$((${BLKCNT} * ${BLKSIZE}))
ROOTUSED=$(((${DFKSIZE} - ${DFKFREE}) * 1024))
IRFSMIN=$(((${ROOTUSED} + (${ADDBLK} * ${BLKSIZE}) + (${ONEMB} - 1)) / ${ONEMB}))
IRFSMAX=$(((${ROOTSIZE} + (${ONEMB} - 1)) / ${ONEMB}))

IMGFILE="$1"
if [ "${IMGFILE}" = "" ]; then
# Create Image file
  while :
  do
    echo ""
    read -r -e -i "${IMGFILE}" -p "Image file to create? " IMGFILE
    if [ "${IMGFILE}" = "" ]; then
      continue
    elif [[ ! "${IMGFILE}" =~ ^/mnt/.*$ && ! "${IMGFILE}" =~ ^/media/.*$ ]]; then
      echo ""
      echo "${IMGFILE} does not begin with /mnt/ or /media/"
      continue
    fi
    if [ -d "${IMGFILE}" ]; then
      echo ""
      echo "${IMGFILE} is a directory"
    elif [ -f "${IMGFILE}" ]; then
      echo ""
      echo -n "${IMGFILE} already exists, Ok to delete (y/n)? "
      while read -r -n 1 -s answer; do
        if [[ "${answer}" = [yYnN] ]]; then
          echo "${answer}"
          if [[ "${answer}" = [yY] ]]; then
            break 2
          else
            break 1
          fi
        fi
      done
    else
      break
    fi
  done
  IRFSSIZE=""
  while :
  do
    echo ""
    read -r -e -i "${IRFSSIZE}" -p "Image ROOT filesystem size (MB) [${IRFSMAX}]? " IRFSSIZE
    if [ "${IRFSSIZE}" = "" ]; then
      IRFSSIZE=${IRFSMAX}
      break
    elif [ ${IRFSSIZE} -ge ${IRFSMIN} ]; then
      break
    else
      echo ""
      echo "Requested image ROOT filesystem size (${IRFSSIZE}) is too small (Minimum = ${IRFSMIN})"
      IRFSSIZE=${IRFSMIN}
    fi
  done
  echo ""
  echo -n "Create ${IMGFILE} [${IRFSSIZE} MB] (y/n)? "
  while read -r -n 1 -s answer; do
    if [[ "${answer}" = [yYnN] ]]; then
      echo "${answer}"
      if [[ "${answer}" = [yY] ]]; then
        break
      else
        errexit "Aborted"
      fi
    fi
  done
  if [ -f "${IMGFILE}" ]; then
    rm "${IMGFILE}"
    if [ $? -ne 0 ]; then
      errexit "Unable to delete existing image file"
    fi
  fi
  ROOTEND=$((${ROOTBEG} + ((${IRFSSIZE} * ${ONEMB}) / 512) - 1))
  truncate -s $(((${ROOTEND} + 1) * 512)) "${IMGFILE}"
  if [ $? -ne 0 ]; then
    errexit "Unable to create image file"
  fi
# create image/partitions
  sync
  fdisk "${IMGFILE}" <<EOF > /dev/null
p
n
p
1
${BOOTBEG}
+${BOOTSIZEM}
t
c
p
n
p
2
${ROOTBEG}
${ROOTEND}
p
w
EOF

  mkloop1
  mkloop2
  mkfs.vfat "${LOOP1}" > /dev/null
  if [ $? -ne 0 ]; then
    errexit "Unable to create image BOOT filesystem"
  fi
  dosfsck "${LOOP1}" > /dev/null
  if [ $? -ne 0 ]; then
    errexit "Image BOOT filesystem appears corrupted"
  fi
  if [ "${ROOT_TYPE}" = "f2fs" ]; then
    mkfs.f2fs "${LOOP2}" > /dev/null
  else
    mkfs.ext4 -q -b ${BLKSIZE} "${LOOP2}" > /dev/null
  fi
  if [ $? -ne 0 ]; then
    errexit "Unable to create image ROOT filesystem"
  fi
  rmloop2
  rmloop1
# Initialise image PARTUUID
  fdisk "${IMGFILE}" <<EOF > /dev/null
p
x
i
0x${PTUUID}
r
p
w
EOF
# Create empty directories in image root partition
  mntimg
  mkdir "${MNTPATH}/dev/" "${MNTPATH}/media/" "${MNTPATH}/mnt/" "${MNTPATH}/proc/" "${MNTPATH}/run/" "${MNTPATH}/sys/" "${MNTPATH}/tmp/"
  if [ $? -ne 0 ]; then
    errexit "Unable to create image directories"
  fi
  chmod a+rwxt "${MNTPATH}/tmp/"
  umntimg
  echo ""
  echo "Starting full backup (for incremental backups, run: $0 ${IMGFILE})"
# END of create image/partitions
else

# Check existing Image
  if [[ ! "${IMGFILE}" =~ ^/mnt/.*$ && ! "${IMGFILE}" =~ ^/media/.*$ ]]; then
    errexit "${IMGFILE} does not begin with /mnt/ or /media/"
  fi
  if [ -d "${IMGFILE}" ]; then
    errexit "${IMGFILE} is a directory"
  elif [ ! -f "${IMGFILE}" ]; then
    errexit "${IMGFILE} not found"
  fi
  echo "Starting incremental backup to ${IMGFILE}"
fi

# rsync root partition
mntimg
sync
rsync -aDH --partial --numeric-ids --delete --force --exclude "${MNTPATH}" --exclude '/dev' --exclude '/media' --exclude '/mnt/*/*' --exclude '/proc' --exclude '/run' --exclude '/sys' \
--exclude '/tmp' --exclude 'lost\+found' --exclude '/etc/udev/rules.d/70-persistent-net.rules' --exclude '/var/lib/asterisk/astdb.sqlite3-journal' / "${MNTPATH}/"
if [[ $? -ne 0 && $? -ne 24 ]]; then
  errexit "Unable to create backup"
fi
sync
umntimg
Milliways
fonte
-1

Abra o terminal e digite 'lsblk -f'.
Isso deve mostrar todos os dispositivos de armazenamento conectados.
Em seguida, digite 'dd if = / dev / [o NOME do seu cartão sd] bs = 1M'.
Isso levará um tempo, portanto você pode executá-lo em segundo plano.
É exatamente da mesma maneira que você faz o backup do seu cartão SD no Linux.

jay jayjay
fonte
Isso faz backup de TUDO, até arquivos desnecessários e indesejáveis.
IgorGanapolsky
3
Isso fará um backup inconsistente, porque em um sistema em execução as coisas mudaram durante o backup!
Ingo