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

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


Action unknown: copypageplugin__copy
projects:linux:manual_backup_scripts:shrink_limit_img

Limited Shrink

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

limited_shrink.sh
#!/bin/bash
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
# ==DIS/AUTOEXEC==
# === Ограниченный shrink образа до заданного размера ===
# 05_limited_shrink.sh — shrink, но не меньше заданного размера в ГБ
#
 
set -euo pipefail
 
LIMIT_GB=30
LIMIT_MB=$((LIMIT_GB * 1024))
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SHRINK_SCRIPT="$SCRIPT_DIR/pishrink_limited.sh"
 
# --- Выбор устройства / начало блока ---
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 "💽 Выберите устройство, где лежит образ .img/.img.gz:"
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
 
[[ "$choice" == "0" || -z "$choice" ]] && echo "❎ Отменено." && exit 0
(( choice < 1 || choice > ${#DEVICES[@]} )) && echo "❌ Неверный выбор." && exit 1
 
SEL_DEV="${DEVICES[$((choice-1))]}"
IFS=":" read -r DEV_NAME DEV_SIZE DEV_MNT <<< "$SEL_DEV"
 
TEMP_MOUNTED=false
if [[ "$DEV_NAME" == "$NAS_PATH" ]]; then
  TARGET_DIR="$NAS_PATH"
  echo "📁 Используем NAS каталог: $TARGET_DIR"
else
  MOUNTED_PATH=$(lsblk -nrpo NAME,MOUNTPOINT "$DEV_NAME" | awk '$2!="" {print $2; exit}')
  if [[ -n "$MOUNTED_PATH" ]]; then
    echo "✅ Используем: $MOUNTED_PATH"
    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"
    if sudo mount "$DEV_NAME" "$MNT_PATH"; then
      echo "✅ Устройство примонтировано: $MNT_PATH"
      TARGET_DIR="$MNT_PATH"
      TEMP_MOUNTED=true
    else
      echo "❌ Не удалось примонтировать."
      exit 1
    fi
  fi
fi
# --- Выбор устройства / конец блока ---
 
# === Поиск образов ===
mapfile -t IMG_LIST < <(find "$TARGET_DIR" -maxdepth 1 -type f \( -name "*.img" -o -name "*.img.gz" \))
if [[ ${#IMG_LIST[@]} -eq 0 ]]; then
  echo "❌ Образы не найдены в $TARGET_DIR"
  $TEMP_MOUNTED && sudo umount "$TARGET_DIR"
  exit 1
fi
 
echo "🗂️ Образы:"
i=1
for img in "${IMG_LIST[@]}"; do
  echo "  $i - $img"
  ((i++))
done
echo "  0 - Отмена"
read -rp "👉 Выбор образа: " img_choice
[[ "$img_choice" == "0" || -z "$img_choice" ]] && echo "❎ Отменено." && $TEMP_MOUNTED && sudo umount "$TARGET_DIR" && exit 0
(( img_choice < 1 || img_choice > ${#IMG_LIST[@]} )) && echo "❌ Неверный выбор." && exit 1
 
IMGFILE="${IMG_LIST[$((img_choice-1))]}"
 
# === Распаковка .gz ===
if [[ "$IMGFILE" == *.gz ]]; then
  UNPACKED="${IMGFILE%.gz}"
  if [[ -f "$UNPACKED" ]]; then
    echo "⚠️ Уже существует распакованный образ: $UNPACKED"
    read -rp "Заменить? (y/N): " confirm_over
    [[ ! "$confirm_over" =~ ^[Yy]$ ]] && echo "❎ Отменено." && exit 0
    rm -f "$UNPACKED"
  fi
  echo "[*] Распаковываю .gz..."
  gunzip -k "$IMGFILE"
  IMGFILE="$UNPACKED"
fi
 
# === Проверка pishrink ===
if [[ ! -x "$SHRINK_SCRIPT" ]]; then
  echo "⚠️ Модифицированный shrink не найден. Скачиваю и распаковываю..."
  curl -fsSL "https://takraztak-wiki.ru/_media/projects:linux:pishrink_limited.tar.gz" -o "${SHRINK_SCRIPT}.tar.gz"
  tar -xzf "${SHRINK_SCRIPT}.tar.gz" -C "$SCRIPT_DIR"
  chmod +x "$SHRINK_SCRIPT"
  rm "${SHRINK_SCRIPT}.tar.gz"
fi
 
# === Резервная копия ===
# BACKUP_IMG="${IMGFILE%.img}_original.img"
# if [[ -f "$BACKUP_IMG" ]]; then
  # echo "⚠️ Резервная копия уже существует: $BACKUP_IMG"
# else
  # echo "📁 Создание резервной копии..."
  # cp --reflink=auto --sparse=always "$IMGFILE" "$BACKUP_IMG" || {
    # echo "❌ Не удалось создать резервную копию."
    # exit 1
  # }
  # echo "✅ Сохранена как $BACKUP_IMG"
# fi
 
# === Запуск ограниченного shrink ===
echo "[*] Применяю ограниченный shrink (не меньше ${LIMIT_GB}ГБ)..."
sudo "$SHRINK_SCRIPT" --max-size-mb "$LIMIT_MB" "$IMGFILE"
 
# === Проверка фактического размера ===
FINAL_BYTES=$(stat -c %s "$IMGFILE")
EXPECTED_BYTES=$((LIMIT_GB * 1024 * 1024 * 1024))
 
if [[ "$FINAL_BYTES" -gt "$EXPECTED_BYTES" ]]; then
  echo "⚠️ Образ всё ещё больше лимита ($((FINAL_BYTES / 1024 / 1024)) МБ > ${LIMIT_MB} МБ). Принудительно обрезаю..."
  truncate -s "$EXPECTED_BYTES" "$IMGFILE"
  FINAL_BYTES_AFTER=$(stat -c %s "$IMGFILE")
  if [[ "$FINAL_BYTES_AFTER" -eq "$EXPECTED_BYTES" ]]; then
    echo "✅ Успешно обрезано до ${LIMIT_GB}ГБ."
  else
    echo "❌ Не удалось обрезать образ до нужного размера."
    exit 1
  fi
else
  echo "✅ Размер уже в пределах лимита (${LIMIT_GB}ГБ)."
fi
 
echo "✅ Shrink завершён: $IMGFILE (лимит: ${LIMIT_GB}ГБ)"
$TEMP_MOUNTED && sudo umount "$TARGET_DIR"
exit 0

*******

projects/linux/manual_backup_scripts/shrink_limit_img.txt · Последнее изменение: 2025/04/11 17:45 —

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