# Описание процесса создания резервной копии Raspberry Pi 4 Существует множество способов создания резервных копий системы, среди которых - использование специализированного ПО, самописные скрипты, которые выполняют копирование/архивирование выбранных директорий, ручное копирование, создание образов дисков и разделов и т.д. Создать резервную копию мало, необходимо также быть уверенным в том, что в случае необходимости, с ранее созданной резервной копии можно восстановиться. Ведь в процессе создания резервной копии, исходные данные могут изменяться - происходит чтение/запись, таким образом, есть вероятность, что в резервную копию попадут не консистентные данные и восстановиться с такой резервной копии будет невозможно. Чтобы избежать подобных проблем, необходимо исключить возможность изменения исходных данных в процессе создания резервных копий. Например, при создании образа системы, необходимо, чтобы раздел, резервную копию которого будем выполнять, не был смонтирован. Этого легко добиться, если это не загрузочный раздел. Но как быть, если нужно создать резервную копию (образ) загрузочного раздела или всего диска? - Необходимо выполнить загрузку с какого-нибудь live-cd и средствами этого самого live-cd создать образ системы. С Raspberry Pi 4 ситуация немного проще, достаточно извлечь SD-карту, создать её образ и сохранить этот образ в надёжном месте. Всё это ручная работа, которая требует времени. ## Один из способов автоматизации создания образа системы Raspberry Pi 4 описан ниже Raspberry Pi 4, 400 и Compute Module 4 используют EEPROM для загрузки системы. Все остальные модели Raspberry Pi используют bootcode.bin файл, расположенный в загрузочной файловой системе. Если не углубляться в детали ([BOOT ORDER](https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#BOOT_ORDER)), EEPROM позволяет выполнять загрузку c SD карты, USB, сети. Такую возможность добавили в одном из обновлений, необходимо убедиться, что используется последняя версия EEPROM. Таким образом, выполнить создание образа SD-карты RPI можно если: - записать образ системы на USB накопитель, подойдёт Raspberry Pi OS lite (); - подключить USB накопитель к RPI; - переключить EEPROM в режим загрузки с USB; - выполнить загрузку с USB; - создать образ SD-карты и передать его в надёжное сетевое хранилище; - вернуть EEPROM в режим загрузки с SD-карты; - перезагрузить RPI. Ничего сложного, осталось найти способ автоматического переключения способов загрузки в EEPROM. И такой способ существует - утилита `rpi-eeprom-config` Нам достаточно двух ключей: -a, --apply -o, --out сохранить текущие настройки EEPROM во внешний файл ```bash pi@host:~ $ sudo rpi-eeprom-config -o ~/eeprom.conf ``` применить конфигурацию EEPROM из файла ```bash pi@host:~ $ sudo rpi-eeprom-config -a ~/eeprom.conf ``` Осталось окончательно сформировать архитектуру нашего решения по созданию образа. **На системе загруженной с SD** 1. Необходимо создать конфигурационный файл EEPROM, который установит загрузку на USB ```bash pi@host:~ $ sudo mkdir /opt/backup_from_usb && sudo vim /opt/backup_from_usb/usb_eeprom.conf ``` ```bash pi@host:~ $ cat /opt/backup_from_usb/usb_eeprom.conf [all] BOOT_UART=0 WAKE_ON_GPIO=1 POWER_OFF_ON_HALT=0 BOOT_ORDER=0xf4 ``` 2. Создать скрипт, который будет выполнять обновление конфигурации EEPROM ```bash pi@host:~ $ vim /opt/backup_from_usb/rpi_usb_boot.sh ``` ```bash #!/bin/bash ################################################################################################### # Скрипт выполняет обновление конфигурации EEPROM Raspberry PI для загрузки с USB. # В директории с этим скриптом должен находится конфигурационный файл EEPROM - $eeprom_conf # Для корректной работы скрипта, EEPROM RPI должен поддерживать режим переключения загрузки SD<=>USB. ################################################################################################### # Убедиться, что запуск происходит от root if [ "$EUID" -ne 0 ] then echo "Скрипт необходимо запускать от администратора" exit fi # Необходимо убедиться, что в папке присутствует конфиг EEPROM для изменения порядка загрузки eeprom_conf="usb_eeprom.conf" if [ ! -e "./$eeprom_conf" ]; then echo Файл настроек EEPROM $eeprom_conf не найден > log 2>&1 exit fi # Необходимо переключить EEPROM на загрузку с USB rpi-eeprom-config -a ./$eeprom_conf # Перезагрузка reboot ``` Добавить права на выполнение ```bash pi@host:~ $ chmod +x /opt/backup_from_usb/rpi_usb_boot.sh ``` 3. Выполнить настройку запуска скрипта по расписанию. *т.к. обновление конфигурации EEPROM необходимо выполнять с привилегиями root, настраивать расписание нужно также пользователя root, чтобы скрипт запускался с повышенными привилегиями.* ```bash pi@host:~ $ sudo crontab -e ``` например, для запуска скрипта каждую среду в 2 часа ночи, необходимо добавить строку ```bash 0 2 * * 3 /opt/backup_from_usb/rpi_usb_boot.sh ``` **На системе загруженной с USB** *для этого нужно запустить скрипт `/opt/backup_from_usb/rpi_usb_boot.sh` от рута или вручную переопределить загрузочный носитель с помощью `sudo rpi-eeprom-config -a /opt/backup_from_usb/usb_eeprom.conf` и перезагрузиться* 4. Обеспечить подключение к хранилищу по SSH на основе ключа ```bash pi@host-usb:~ $ ssh-keygen pi@host-usb:~ $ ssh-copy-id user@nas ``` 5. Создать конфигурационный файл EEPROM, который вернёт загрузку на SD ```bash pi@host-usb:~ $ sudo mkdir opt/backup_rpi && sudo vim /opt/backup_rpi/sd_eeprom.conf ``` ```bash pi@host-usb:~ $ cat /opt/backup_rpi/sd_eeprom.conf [all] BOOT_UART=0 WAKE_ON_GPIO=1 POWER_OFF_ON_HALT=0 BOOT_ORDER=0xf1 ``` 6. Подготовить основной скрипт, который выполнит создание образа SD-карты и передаст его по SSH в сетевое хранилище ```bash pi@host-usb:~ $ sudo vim /opt/backup_rpi/rpi_backup.sh ``` ```bash #!/bin/bash ################################################################################################### # Скрипт создаёт образ SD-карты Raspberry PI и отправляет его на удалённый сервер по SSH, # при этом на удалённом сервере происходит сжатие образа для экономии места. # Сжатие происходит на удалённом сервере, чтобы минимизировать операции записи на Flash память, # с которой произведена загрузка RPI. # После создания образа, происходит обновление конфигурации EEPROM Raspberry PI для загрузки с SD карты. # В директории с этим скриптом должен находится конфигурационный файл EEPROM - $eeprom_conf # Для корректной работы скрипта, EEPROM RPI должен поддерживать режим переключения загрузки SD<=>USB. ################################################################################################### # Убедиться, что запуск происходит от root if [ "$EUID" -ne 0 ] then echo "Скрипт необходимо запускать от администратора" exit fi # Удалённый сервер. Необходимо предварительно обеспечить доступ по ключам - ssh-keygen && ssh-sopy-id server=user@nas # Путь сохранения на удалённом сервре remote_path=/mnt/main/data/Backup/bastion_rpi # Необходимо убедиться, что в папке присутствует конфиг EEPROM для изменения порядка загрузки eeprom_conf="sd_eeprom.conf" if [ ! -e "./$eeprom_conf" ]; then ssh $server "echo Файл настроек EEPROM $eeprom_conf не найден" > $remote_path/lastlog 2>&1 exit fi # Имя образа name=$(echo $(date +%Y-%m-%d)_${HOSTNAME}_image.img.gz | sed 's/-usb//') # Имя диска, над которым будем работать. SD в RPI называется mmcblk0 disk=/dev/mmcblk0 # запишем в переменную последний сектор последнего раздела диска last_sector=$(fdisk -l -o end $disk | tail -1) # Считаем, что размер сектора составляет 512 Байт, тогда необходимо сохранить ($last_sector+1)*512 Байт. # Или ($last_sector+1)*512/1024/1024 Мб. count=$(($(($last_sector+1))*512/1024/1024)) # Команда создания образа dd if=$disk bs=1M count=$count conv=noerror,sync | ssh $server "gzip -c > $remote_path/$name 2>> $remote_path/lastlog" && \ ssh $server "echo `date +"%A, %d %B %Y"` - Образ создан успешно >> $remote_path/log" || \ ssh $server "echo `date +"%A, %d %B %Y"` - При создании образа произошла ошибка >> $remote_path/log" # Необходимо хранить только последние 20 строк в файле log ssh $server "echo $(tail -20 log) > $remote_path/log" # Необходимо хранить только последние 3 резервные копии count_copies=3 ssh $server "find . -type f -name '*_image.img.gz' -printf '%T@ %p\n' | sort -n | cut -d' ' -f 2- | tail -n +$(($count_copies+1)) | xargs rm -f --" # Необходимо переключить EEPROM на загрузку с SD карты rpi-eeprom-config -a ./$eeprom_conf # Перезагрузка reboot ``` Добавить права на выполнение ```bash pi@host-usb:~ $ sudo chmod +x /opt/backup_rpi/rpi_backup.sh ``` 7. Обеспечить выполнение скрипта при загрузке с USB. Рассмотрим 3 способа. 7.1. /etc/rc.d/rc.local Для выполнения пользовательского скрипта при загрузке, достаточно указать к нему полный путь в файле `/etc/rc.d/rc.local`. Затем необходимо добавить права на выполнение ```bash pi@host-usb:~ $ chmod +x /etc/rc.d/rc.local ``` 7.2. crontab Добавить задание в crontab с параметром `@reboot` ```bash @reboot /opt/backup_rpi/rpi_backup.sh ``` 7.3. Сервис systemd Для этого вам нужно создать скрипт запуска systemd и поместить его в каталог `/etc/systemd/system/`. ```bash pi@host-usb:~ $ vim /etc/systemd/system/rpi_backup.service ``` ```bash pi@host-usb:~ $ cat /etc/systemd/system/rpi_backup.service [Unit] Description=Run a Backup Script at Startup After=default.target [Service] ExecStart=/opt/scripts/rpi_backup.sh [Install] WantedBy=default.target ``` ***