Это старая версия документа!
Создание резервной копии SD карты
Скрипт создания резервной копии SD карты на USB носитель
- backup_sd.sh
#!/bin/bash
# ==AUTOEXEC==
# === Резервирование SD ===
# * Резервирование SD карты с остановкой wireguard
# * и перезапуском после окончания
# * в локальной сети wireguard останавливается и
# * запускается резервное копирование
# * копия после создания сжимается (или нет, по выбору), в имени указывается
# * комментарий запрошенный при запуске скрипта
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
# === Самозащита: запускаем теневую копию ===
if [[ "$0" == "$BASH_SOURCE" && -z "$_SAFE_BACKUP_CLONE" ]]; then
TMP_CLONE=$(mktemp /tmp/safe-backup-XXXXXX.sh)
cp "$0" "$TMP_CLONE"
chmod +x "$TMP_CLONE"
echo "🚨 Запуск временной копии: $TMP_CLONE"
_SAFE_BACKUP_CLONE=1 exec "$TMP_CLONE" "$@"
fi
# Путь к папке для бэкапов на SSD
BACKUP_DIR="/mnt/backup"
# Устройство SD-карты (проверьте имя командой lsblk)
SD_CARD="/dev/mmcblk0"
# Текущая дата и время для формирования имени файла
DATE=$(date +"%Y-%m-%d_%H-%M-%S")
# Меню выбора действия
echo "=== Меню ==="
echo "1. Создать резервную копию (сжать gzip)"
echo "2. Создать резервную копию (без сжатия)"
echo "0. Выход"
echo "Введите номер действия:"
read CHOICE
if [ "$CHOICE" == "0" ]; then
echo "🚪 Выход из скрипта."
exit 0
fi
if [ "$CHOICE" != "1" ] && [ "$CHOICE" != "2" ]; then
echo "❌ Неверный выбор. Выход."
exit 1
fi
# Запрос комментария у пользователя
echo "Введите комментарий к резервной копии (или оставьте пустым):"
read COMMENT
if [ -z "$COMMENT" ]; then
COMMENT="Без комментария"
fi
# Функция транслитерации кириллицы
transliterate() {
echo "$1" | sed -e 's/а/a/g' -e 's/б/b/g' -e 's/в/v/g' -e 's/г/g/g' \
-e 's/д/d/g' -e 's/е/e/g' -e 's/ё/e/g' -e 's/ж/zh/g' \
-e 's/з/z/g' -e 's/и/i/g' -e 's/й/j/g' -e 's/к/k/g' \
-e 's/л/l/g' -e 's/м/m/g' -e 's/н/n/g' -e 's/о/o/g' \
-e 's/п/p/g' -e 's/р/r/g' -e 's/с/s/g' -e 's/т/t/g' \
-e 's/у/u/g' -e 's/ф/f/g' -e 's/х/h/g' -e 's/ц/ts/g' \
-e 's/ч/ch/g' -e 's/ш/sh/g' -e 's/щ/shch/g' -e 's/ъ/_/g' \
-e 's/ы/y/g' -e 's/ь/_/g' -e 's/э/e/g' -e 's/ю/yu/g' \
-e 's/я/ya/g' -e 's/А/A/g' -e 's/Б/B/g' -e 's/В/V/g' \
-e 's/Г/G/g' -e 's/Д/D/g' -e 's/Е/E/g' -e 's/Ё/E/g' \
-e 's/Ж/ZH/g' -e 's/З/Z/g' -e 's/И/I/g' -e 's/Й/J/g' \
-e 's/К/K/g' -e 's/Л/L/g' -e 's/М/M/g' -e 's/Н/N/g' \
-e 's/О/O/g' -e 's/П/P/g' -e 's/Р/R/g' -e 's/С/S/g' \
-e 's/Т/T/g' -e 's/У/U/g' -e 's/Ф/F/g' -e 's/Х/H/g' \
-e 's/Ц/TS/g' -e 's/Ч/CH/g' -e 's/Ш/SH/g' -e 's/Щ/SHCH/g' \
-e 's/Ъ/_/g' -e 's/Ы/Y/g' -e 's/Ь/_/g' -e 's/Э/E/g' \
-e 's/Ю/YU/g' -e 's/Я/YA/g' | tr ' ' '_' | tr -cd '[:alnum:]_'
}
# Очистка комментария перед транслитерацией для имени файла
CLEAN_COMMENT=$(echo "$COMMENT" | iconv -f utf-8 -t utf-8 -c | tr -cd '[:alnum:]а-яА-ЯёЁ .,()_+-' | sed 's/[[:space:]]\+/ /g' | xargs)
SAFE_COMMENT=$(transliterate "$CLEAN_COMMENT")
# Формирование имени файла бэкапа
EXT="img"
if [ "$CHOICE" == "1" ]; then
EXT="img.gz"
fi
BACKUP_FILE="$BACKUP_DIR/backup_${DATE}_${SAFE_COMMENT}.$EXT"
# Проверка, что папка для бэкапов существует
if [ ! -d "$BACKUP_DIR" ]; then
echo "Ошибка: папка $BACKUP_DIR не найдена! Проверьте, смонтирован ли SSD."
exit 1
fi
# Определение IP клиента и проверка на WireGuard-подсеть
CLIENT_IP=$(who am i | awk '{print $5}' | grep -oE '[0-9.]+')
if [[ "$CLIENT_IP" =~ ^10\. ]]; then
echo "⚠️ Обнаружено подключение по WireGuard ($CLIENT_IP) — не отключаем wg-quick@wg0"
WG_SKIP=1
else
echo "⏸️ Останавливаем WireGuard (wg-quick@wg0)..."
sudo systemctl stop wg-quick@wg0
WG_STOPPED=1
fi
# Сброс буферов перед резервным копированием
echo "💾 Сброс буферов на диск..."
sync
# Получение общего размера устройства
SD_SIZE=$(sudo blockdev --getsize64 "$SD_CARD" 2>/dev/null || echo 0)
HUMAN_SIZE=$(numfmt --to=iec $SD_SIZE)
echo "📦 Ожидаемый общий размер: $HUMAN_SIZE"
ESTIMATED_MIN=$(numfmt --to=iec $((SD_SIZE * 30 / 100)))
ESTIMATED_MAX=$(numfmt --to=iec $((SD_SIZE * 70 / 100)))
echo "🧮 После сжатия ожидаемый размер архива: от $ESTIMATED_MIN до $ESTIMATED_MAX"
# Резервное копирование через dd с отображением прогресса
echo "📋 Копирование с помощью dd..."
if [ "$CHOICE" == "1" ]; then
sudo dd if=$SD_CARD bs=4M status=progress | gzip > "$BACKUP_FILE"
else
sudo dd if=$SD_CARD bs=4M status=progress of="$BACKUP_FILE"
fi
echo "✅ Чтение завершено."
# Запуск WireGuard после резервного копирования (если мы его останавливали)
if [[ "$WG_STOPPED" == "1" ]]; then
echo "▶️ Запускаем WireGuard обратно..."
sudo systemctl start wg-quick@wg0
fi
# Сохранение комментария в лог-файле
echo -e "$DATE - $COMMENT" | iconv -f utf-8 -t utf-8 -c | tee -a "$BACKUP_DIR/backup_log.txt" > /dev/null
# Вывод размера итогового файла
FILE_SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
echo "📦 Размер резервной копии: $FILE_SIZE"
# Создание контрольной суммы SHA256
SHA_FILE="$BACKUP_FILE.sha256"
echo "🔐 Создаём контрольную сумму SHA256..."
sha256sum "$BACKUP_FILE" | tee "$SHA_FILE"
echo "🎉 Резервное копирование завершено полностью!"
echo "✅ Резервная копия: $BACKUP_FILE"
echo "🔐 Контрольная сумма сохранена: $SHA_FILE"
MarkDown
# Скрипт `backup-sd.sh`
Расширенный скрипт резервного копирования SD-карт с поддержкой shrink, сжатия, логирования и CLI-интерфейса. Подходит для автоматизации задач резервного копирования на Raspberry Pi и аналогичных устройствах.
—
## 📦 Поддерживаемые аргументы
Аргумент | Значение / Описание | Пример |
–comment=… | Комментарий для имени файла | –comment=«ежедневный» |
–compress=gzip | Метод сжатия: `gzip`, `xz`, `zstd`, `none` | –compress=zstd |
–shrink | Включить уменьшение образа (shrink) | –shrink |
–no-shrink | Не уменьшать образ | –no-shrink |
–sha256 | Посчитать SHA256 | –sha256 |
–no-sha256 | Не считать SHA256 | –no-sha256 |
–device=/dev/… | Устройство для копирования | –device=/dev/mmcblk0 |
–source=/path/to.img | Использовать готовый `.img`, не делать `dd` | –source=/mnt/usb/backup.img |
–keep-img | Не удалять `.img` после shrink | –keep-img |
–keep-days=N | Удалять копии старше N дней | –keep-days=7 |
–keep-count=N | Хранить не более N последних копий | –keep-count=3 |
–log=/path/to.log | Путь к лог-файлу | –log=/mnt/usb/backup.log |
–template=ШАБЛОН | Шаблон имени файла: `%DATE%`, `%COMMENT%` | –template=«wash_%DATE%_%COMMENT%» |
| | |
-n`, –non-interactive | Без меню, полностью через параметры | –non-interactive |
| -y, `–auto-install` | Автоустановка зависимостей | –auto-install |
| -h, –help | Показать справку | –help |
| –version | Показать версию скрипта | –version'' | | |
—
## 🧪 Примеры запуска
### 📦 Съём и сжатие:
```bash
./backup-sd.sh –comment=«ночной» –compress=zstd –shrink –sha256 –device=/dev/mmcblk0 -n
```
### 🗃️ Обработка существующего `.img`, shrink + gzip:
```bash
./backup-sd.sh –source=/mnt/usb/old.img –compress=gzip –shrink –comment=«старый образ» –keep-img -n
```
### ♻️ Просто сжать `.img`, без shrink:
```bash
./backup-sd.sh –source=image.img –compress=zstd –no-shrink –comment=«просто сжали» -n
```
—
## 📝 Замечания
- Поддерживает `shrink` через встроенный `pishrink.sh`, загружаемый при необходимости.
- Все параметры можно комбинировать.
- Подходит для cron, systemd, ручных задач и GUI-обёрток.