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 —