====== Создание образа с live системы ====== //**Входит в набор [[projects:linux:manual_backup_scripts|rPi Seal]]**// Снятие образа в img файл с live системы на примонтированные устройства (USB/NAS)\\ #!/bin/bash export LANG=en_US.UTF-8 export LC_ALL=en_US.UTF-8 # ==DIS/AUTOEXEC== # === Create Img === # 04_create_image.sh — создание ограниченного образа текущей системы Raspberry Pi # с отключением журналов для минимизации записей на SD карту # echo "Снятие образа с live системы" echo "──────────────────────────────" set -euo pipefail # --- Поиск целевых устройств (включая NAS) --- NAS_PATH="/mnt/backup_nas" if mountpoint -q "$NAS_PATH"; then mapfile -t DEVICES < <(lsblk -nrpo NAME,SIZE,MOUNTPOINT | grep -E "/dev/sd|/dev/nvme" | awk '{print $1":"$2":"$3}') DEVICES+=("$NAS_PATH::NAS") else mapfile -t DEVICES < <(lsblk -nrpo NAME,SIZE,MOUNTPOINT | grep -E "/dev/sd|/dev/nvme" | awk '{print $1":"$2":"$3}') fi if [[ ${#DEVICES[@]} -eq 0 ]]; then echo "❌ Нет доступных устройств." exit 1 fi echo "💾 Выберите место для сохранения образа:" i=1 for dev in "${DEVICES[@]}"; do IFS=":" read -r name size mnt <<< "$dev" label="" [[ "$mnt" == "NAS" ]] && label="🛧 сетевой диск" [[ -z "$mnt" && -z "$label" ]] && label="🔌 не примонтировано" echo "$i - $name $size $mnt $label" ((i++)) done echo "0 - Отмена" read -rp "👉 Ваш выбор: " choice if ! [[ "$choice" =~ ^[0-9]+$ ]] || (( choice < 1 || choice > ${#DEVICES[@]} )); then echo "❎ Отменено или неверный ввод." exit 0 fi SEL_DEV="${DEVICES[$((choice-1))]}" IFS=":" read -r DEV_NAME DEV_SIZE DEV_MNT <<< "$SEL_DEV" # Проверка на USB (влияние на сеть) DEV_BUS=$(udevadm info -q property -n "$DEV_NAME" 2>/dev/null | grep ID_BUS= | cut -d= -f2 || true) DEV_USB_DRIVER=$(udevadm info -q property -n "$DEV_NAME" 2>/dev/null | grep ID_USB_DRIVER= | cut -d= -f2 || true) if [[ "${DEV_BUS:-}" == "usb" && "${DEV_USB_DRIVER:-}" =~ "usb-storage" ]]; then echo "⚠️ Внимание: Устройство подключено через USB." echo " Если используется USB 3.0 — возможны отказы сети (Ethernet) во время записи." echo " Рекомендуется использовать NAS или USB 2.0 для надёжности." echo "" fi # Определение целевого каталога TEMP_MOUNTED=false if [[ "$DEV_NAME" == "$NAS_PATH" ]]; then TARGET_DIR="$NAS_PATH" else MOUNTED_PATH=$(lsblk -nrpo NAME,MOUNTPOINT "$DEV_NAME" | awk '$2!="" {print $2; exit}') if [[ -n "$MOUNTED_PATH" ]]; then TARGET_DIR="$MOUNTED_PATH" else i=0 while true; do MNT_PATH="/mnt/rpi_target$i" if ! mountpoint -q "$MNT_PATH"; then break fi ((i++)) done sudo mkdir -p "$MNT_PATH" FIRST_PART=$(lsblk -nrpo NAME "$DEV_NAME" | grep -v "^$DEV_NAME" | head -n1) if [[ -z "$FIRST_PART" ]]; then echo "❌ Не найден раздел на выбранном устройстве." exit 1 fi if sudo mount "$FIRST_PART" "$MNT_PATH"; then echo "✅ Раздел $FIRST_PART примонтирован в $MNT_PATH" TARGET_DIR="$MNT_PATH" TEMP_MOUNTED=true else echo "❌ Не удалось примонтировать $FIRST_PART." exit 1 fi fi fi # --- Подготовка имени файла --- DATE=$(date +%F_%H-%M-%S) echo "" echo "📁 Выберите способ задания имени файла:" echo "1 - 📅 Использовать стандартное имя ($DATE.img)" echo "2 - ✏️ Ввести своё имя вручную (по умолчанию: $DATE)" echo "0 - ❌ Отмена" read -rp "👉 Ваш выбор: " name_choice case "$name_choice" in 1) IMG_NAME="$DATE.img" ;; 2) echo -n "📝 Имя для создаваемого образа [по умолчанию: $DATE]: " read -r CUSTOM_NAME IMG_NAME="${CUSTOM_NAME:-$DATE}" [[ ! "$IMG_NAME" =~ \.img$ ]] && IMG_NAME+=".img" ;; 0|"") echo "❎ Отменено." exit 0 ;; *) echo "❌ Неверный выбор." exit 1 ;; esac FINAL_IMG="$TARGET_DIR/$IMG_NAME" # --- Проверка перезаписи --- if [[ -f "$FINAL_IMG" ]]; then echo "⚠️ Файл уже существует: $FINAL_IMG" read -rp "❗ Перезаписать? [y/N]: " overwrite [[ "${overwrite,,}" != "y" ]] && echo "❎ Отменено." && exit 0 fi # --- Остановка сервисов --- echo "[*] Остановка логов и фоновых сервисов..." SERVICES=("rsyslog" "systemd-journald" "apt-daily.timer" "docker") for svc in "${SERVICES[@]}"; do if systemctl is-active --quiet "$svc"; then echo "⏸️ Останавливаю $svc..." sudo systemctl stop "$svc" || true fi done sync sudo sysctl -w vm.drop_caches=3 >/dev/null || true # --- Расчёт объёма --- echo "[*] Определение размера /dev/mmcblk0..." END_SECTOR=$(sudo fdisk -l /dev/mmcblk0 | awk '/mmcblk0p[0-9]+/ { end=$3 } END { print end }') SECTOR_SIZE=$(sudo blockdev --getss /dev/mmcblk0) TOTAL_BYTES=$(( (END_SECTOR + 1) * SECTOR_SIZE )) TOTAL_MB=$(( (TOTAL_BYTES + 1024*1024 - 1) / (1024*1024) + 16 )) # --- Снятие образа --- echo "[*] Снимаю образ: $FINAL_IMG ($TOTAL_MB МБ)..." sudo dd if=/dev/mmcblk0 of="$FINAL_IMG" bs=1M count="$TOTAL_MB" status=progress sync # --- Проверка --- if sudo fdisk -l "$FINAL_IMG" >/dev/null 2>&1; then echo "✅ Образ сохранён: $FINAL_IMG" else echo "❌ Образ создан, но таблица разделов не читается." exit 1 fi # --- Очистка --- if $TEMP_MOUNTED; then sudo umount "$TARGET_DIR" && sudo rmdir "$TARGET_DIR" fi # --- Восстановление сервисов --- echo "[*] Восстановление остановленных сервисов..." for svc in "${SERVICES[@]}"; do echo "▶️ Запуск $svc..." sudo systemctl start "$svc" || echo "⚠️ Не удалось запустить $svc" done exit 0 ===== ******* ===== [[https://boosty.to/takraztak/donate|Поддержать через Boosty]]