Инструменты пользователя

Инструменты сайта


Action unknown: copypageplugin__copy
projects:linux:manual_backup_scripts:create_img_sd_usb

Создание образа с sd/usb носителей

Входит в набор rPi Seal

Снятие образа в img файл с live системы на примонтированные устройства (USB/NAS)

create_image.sh
#!/bin/bash
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
# ==DIS/AUTOEXEC==
# === Create Img from selected device ===
# 04.2_create_image.sh — создание образа выбранного внешнего устройства (например, SD-карты)
 
echo "снятие образа с выбранного устройства"
echo "───────────────────────────────────────"
 
set -euo pipefail
 
# --- Выбор устройства-источника ---
echo "📦 Доступные устройства-источники для создания образа:"
mapfile -t SOURCE_DEVS < <(lsblk -dnrpo NAME,SIZE,MODEL | grep -E "/dev/sd|/dev/mmcblk" | grep -v "/dev/mmcblk0")
if [[ ${#SOURCE_DEVS[@]} -eq 0 ]]; then
  echo "❌ Не найдено подходящих устройств."
  exit 1
fi
 
i=1
for dev in "${SOURCE_DEVS[@]}"; do
  echo "$i - $dev"
  ((i++))
done
 
echo "0 - ❌ Отмена"
read -rp "👉 Выберите устройство-источник: " src_choice
 
if ! [[ "$src_choice" =~ ^[0-9]+$ ]] || (( src_choice < 1 || src_choice > ${#SOURCE_DEVS[@]} )); then
  echo "❎ Отменено или неверный ввод."
  exit 0
fi
 
SRC_LINE="${SOURCE_DEVS[$((src_choice-1))]}"
SRC_DEV=$(echo "$SRC_LINE" | awk '{print $1}')
SRC_SIZE=$(echo "$SRC_LINE" | awk '{print $2}')
 
# --- Поиск целевых устройств (включая 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 "   Возможны отказы сети при записи."
  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 "[*] Снимаю образ: $FINAL_IMG$SRC_DEV)..."
sync
sudo dd if="$SRC_DEV" of="$FINAL_IMG" bs=4M status=progress conv=fsync
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
 
exit 0
projects/linux/manual_backup_scripts/create_img_sd_usb.txt · Последнее изменение: 2025/04/11 10:32 —

Если не указано иное, содержимое этой вики предоставляется на условиях следующей лицензии: CC Attribution 4.0 International
CC Attribution 4.0 International Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki