Upload files to "/"

This commit is contained in:
crowetic 2025-04-03 02:40:07 +00:00
parent 66cff87421
commit f867503a57
2 changed files with 304 additions and 0 deletions

229
auto-shrink-compress-img.sh Normal file
View File

@ -0,0 +1,229 @@
#!/bin/bash
set -e
SECTOR_SIZE=512
PADDING_MB=4
IMAGE=""
RESIZED_IMAGE=""
COMPRESSED_NAME=""
echo "==== 🔍 Smart SD Image Shrinker ===="
# === Step 1: Find .img files ===
mapfile -t IMAGES < <(find . -maxdepth 1 -type f -name "*.img" | sort)
if [ ${#IMAGES[@]} -eq 0 ]; then
echo "❌ No .img files found in the current directory."
exit 1
fi
echo ""
echo "📂 Found the following .img files:"
for i in "${!IMAGES[@]}"; do
printf " [%d] %s\n" "$((i+1))" "${IMAGES[$i]}"
done
echo ""
read -p "👉 Enter the number of the image you want to shrink: " SELECTION
if ! [[ "$SELECTION" =~ ^[0-9]+$ ]] || [ "$SELECTION" -lt 1 ] || [ "$SELECTION" -gt "${#IMAGES[@]}" ]; then
echo "❌ Invalid selection."
exit 1
fi
IMAGE="${IMAGES[$((SELECTION-1))]}"
BASENAME=$(basename "$IMAGE")
echo "✅ Selected: $IMAGE"
echo ""
# === Step 2: Select auto or manual sizing ===
echo "📏 Choose target size mode:"
echo " [1] Auto-select smallest SD card (adds 2GB headroom)"
echo " [2] Choose target SD card size manually"
read -p "👉 Enter your choice [1-2]: " SIZE_MODE
if [[ "$SIZE_MODE" != "1" && "$SIZE_MODE" != "2" ]]; then
echo "❌ Invalid selection."
exit 1
fi
# === Step 3: Auto-fix GPT if needed ===
echo "[*] Pre-checking GPT for leftover space issues..."
echo -e "w\ny\n" | sudo gdisk "$IMAGE" >/dev/null 2>&1 || true
# === Step 4: Attach image to loop device ===
echo "📌 Attaching image to loop device..."
LOOP_DEV=$(sudo losetup --show -Pf "$IMAGE")
# === Step 5: Detect rootfs ===
PARTS=$(lsblk -nrpo NAME "$LOOP_DEV" | grep -E "$LOOP_DEV"p)
ROOT_PART=$(for P in $PARTS; do lsblk -bno SIZE "$P" | awk -v p="$P" '{print $1, p}'; done | sort -nr | head -n1 | awk '{print $2}')
if [ -z "$ROOT_PART" ]; then
echo "❌ Error: Couldn't detect root partition."
sudo losetup -d "$LOOP_DEV"
exit 1
fi
PART_NUM=$(basename "$ROOT_PART" | grep -o '[0-9]*$')
echo "🔍 Detected rootfs: $ROOT_PART (Partition #$PART_NUM)"
# === Step 6: Unmount if mounted ===
sudo umount "$ROOT_PART" 2>/dev/null || true
# === Step 7: Determine used space + headroom ===
USED_MB=$(sudo df -m "$ROOT_PART" | awk 'NR==2 {print $3}')
REQUIRED_MB=$(( USED_MB + 2048 ))
# === Define known SD card sizes (actual usable MB) ===
declare -A SD_SIZES
SD_SIZES=(
["8GB"]=6900
["16GB"]=13500
["32GB"]=29000
["64GB"]=59000
["128GB"]=119000
)
# === Determine final TARGET_SIZE_MB ===
if [ "$SIZE_MODE" == "1" ]; then
echo "🧠 Auto-selecting smallest SD card size to fit $REQUIRED_MB MB..."
for label in 8GB 16GB 32GB 64GB 128GB; do
if [ "$REQUIRED_MB" -le "${SD_SIZES[$label]}" ]; then
TARGET_SIZE_MB=${SD_SIZES[$label]}
SIZE_LABEL=$label
echo "✅ Selected size: $SIZE_LABEL (${TARGET_SIZE_MB} MB)"
break
fi
done
if [ -z "$SIZE_LABEL" ]; then
echo "❌ No supported SD size large enough. Required: $REQUIRED_MB MB"
sudo losetup -d "$LOOP_DEV"
exit 1
fi
else
echo ""
echo "📐 Choose target SD card size:"
OPTIONS=("8GB" "16GB" "32GB" "64GB" "128GB")
for i in "${!OPTIONS[@]}"; do
printf " [%d] %s\n" "$((i+1))" "${OPTIONS[$i]}"
done
read -p "👉 Enter your choice [1-5]: " SIZE_CHOICE
if ! [[ "$SIZE_CHOICE" =~ ^[1-5]$ ]]; then
echo "❌ Invalid selection."
sudo losetup -d "$LOOP_DEV"
exit 1
fi
SIZE_LABEL=${OPTIONS[$((SIZE_CHOICE-1))]}
TARGET_SIZE_MB=${SD_SIZES[$SIZE_LABEL]}
if [ "$REQUIRED_MB" -gt "$TARGET_SIZE_MB" ]; then
echo "⚠️ $SIZE_LABEL is too small to hold this data (need $REQUIRED_MB MB)"
echo "🔁 Auto-selecting next size up..."
FOUND=0
for label in 16GB 32GB 64GB 128GB; do
if [ "$REQUIRED_MB" -le "${SD_SIZES[$label]}" ]; then
TARGET_SIZE_MB=${SD_SIZES[$label]}
SIZE_LABEL=$label
echo "✅ Switched to: $SIZE_LABEL (${TARGET_SIZE_MB} MB)"
FOUND=1
break
fi
done
if [ "$FOUND" -eq 0 ]; then
echo "❌ No SD size large enough. Required: $REQUIRED_MB MB"
sudo losetup -d "$LOOP_DEV"
exit 1
fi
else
echo "✅ Selected target: $SIZE_LABEL (${TARGET_SIZE_MB} MB)"
fi
fi
# === Step 8: fsck and resize ===
echo "🔧 Running fsck and shrinking rootfs..."
sudo e2fsck -fy "$ROOT_PART" | tee fsck.log
if grep -q "FILE SYSTEM WAS MODIFIED" fsck.log; then
echo "🔁 FS was modified. Re-checking..."
sudo e2fsck -fy "$ROOT_PART"
fi
rm -f fsck.log
sudo resize2fs "$ROOT_PART" "${TARGET_SIZE_MB}M"
# === Step 9: Resize partition ===
START_SECTOR=$(sudo parted -s "$IMAGE" unit s print | grep "^ $PART_NUM" | awk '{print $2}' | sed 's/s//')
TARGET_SECTORS=$((TARGET_SIZE_MB * 1024 * 1024 / SECTOR_SIZE))
END_SECTOR=$((START_SECTOR + TARGET_SECTORS - 1))
PART_TYPE=$(sudo parted -s "$IMAGE" print | grep "Partition Table" | awk '{print $3}')
echo "🧠 Partition table type: $PART_TYPE"
if [[ "$PART_TYPE" == "msdos" ]]; then
echo "🔧 Updating MBR partition..."
PART_DEV="./${BASENAME}${PART_NUM}"
echo "🧪 Looking for partition entry named: $PART_DEV"
echo "📄 sfdisk --dump preview:"
sudo sfdisk --dump "$IMAGE" | grep "$PART_DEV"
TEMP_SFDISK="temp-sfdisk-edit.txt"
echo "📄 Updating partition entry for: $PART_DEV"
sudo sfdisk --dump "$IMAGE" | awk -v dev="$PART_DEV" -v start="$START_SECTOR" -v end="$END_SECTOR" '
BEGIN { updated = 0 }
{
if ($1 == dev) {
size = end - start + 1
print $1 " : start=" start ", size=" size ", type=83"
updated = 1
} else {
print $0
}
}
END {
if (updated == 0) {
print "❌ Failed to update partition: entry not found for " dev > "/dev/stderr"
exit 1
}
}' > "$TEMP_SFDISK"
sudo sfdisk "$IMAGE" < "$TEMP_SFDISK"
rm -f "$TEMP_SFDISK"
elif [[ "$PART_TYPE" == "gpt" ]]; then
echo "🔧 Updating GPT partition..."
sudo sgdisk --delete=$PART_NUM "$IMAGE"
sudo sgdisk --new=$PART_NUM:$START_SECTOR:$END_SECTOR "$IMAGE"
else
echo "❌ Unknown partition type: $PART_TYPE"
sudo losetup -d "$LOOP_DEV"
exit 1
fi
# === Step 10: Detach + truncate resized image ===
sudo losetup -d "$LOOP_DEV"
TRUNC_SIZE=$(( (END_SECTOR + (PADDING_MB * 1024 * 1024 / SECTOR_SIZE)) * SECTOR_SIZE ))
RESIZED_IMAGE="resized-${SIZE_LABEL}-${BASENAME}"
echo "✂️ Creating resized image: $RESIZED_IMAGE"
dd if="$IMAGE" of="$RESIZED_IMAGE" bs=1M count=$((TRUNC_SIZE / 1024 / 1024)) status=progress
# === Step 11: Compress ===
echo "📦 Compressing to .xz..."
xz -T0 -9 "$RESIZED_IMAGE"
echo ""
echo "🔍 Verifying compressed image..."
if xz -t "${RESIZED_IMAGE}.xz"; then
echo "✅ Compression verified!"
else
echo "❌ Compression failed! The .xz file may be corrupted."
exit 1
fi
echo ""
echo "✅ Done! Output: ${RESIZED_IMAGE}.xz"

View File

@ -0,0 +1,75 @@
#!/bin/bash
set -e
RESIZE_SCRIPT="./auto-shrink-compress-img.sh"
echo "==== 🧠 SD Card Disk Imager + Auto Resize ===="
# === Step 1: Detect likely SD card devices ===
echo ""
echo "📦 Scanning for removable storage devices..."
mapfile -t DISKS < <(lsblk -dpno NAME,MODEL,SIZE,RM | awk '$4 == 1 { print $1 }')
if [ ${#DISKS[@]} -eq 0 ]; then
echo "❌ No removable (likely SD card) devices found!"
exit 1
fi
echo ""
echo "📂 Found the following removable block devices:"
for i in "${!DISKS[@]}"; do
disk_info=$(lsblk -dno NAME,MODEL,SIZE "${DISKS[$i]}")
printf " [%d] %s\n" "$((i+1))" "$disk_info"
done
echo ""
read -p "👉 Enter the number of the disk to back up: " SELECTION
if ! [[ "$SELECTION" =~ ^[0-9]+$ ]] || [ "$SELECTION" -lt 1 ] || [ "$SELECTION" -gt "${#DISKS[@]}" ]; then
echo "❌ Invalid selection."
exit 1
fi
DISK="${DISKS[$((SELECTION-1))]}"
echo "✅ Selected disk: $DISK"
echo ""
# === Step 2: Ask for image filename ===
read -p "💾 Enter a name for the output image file (no extension): " IMG_NAME
IMG_FILE="${IMG_NAME}.img"
if [ -f "$IMG_FILE" ]; then
echo "⚠️ File '$IMG_FILE' already exists! Please choose a different name."
exit 1
fi
echo ""
echo "📸 Creating disk image from $DISK..."
sudo dd if="$DISK" of="$IMG_FILE" bs=4M status=progress conv=fsync
echo ""
echo "✅ Disk image created: $IMG_FILE"
# === Step 3: Ask if user wants to auto-shrink ===
echo ""
if [ ! -f "$RESIZE_SCRIPT" ]; then
echo "⚠️ Resize script '$RESIZE_SCRIPT' not found! Skipping auto-shrink."
exit 0
fi
echo "⏳ Would you like to resize & compress this image using:"
echo " $RESIZE_SCRIPT"
echo ""
echo "It will auto-run in 30 seconds if no answer is given."
read -t 30 -p "Type 'n' to skip or press [Enter] to run: " ANSWER
if [[ "$ANSWER" =~ ^[Nn]$ ]]; then
echo "🚫 Skipping resize/compression."
exit 0
fi
# === Step 4: Run the shrink script ===
echo ""
echo "🚀 Running auto-shrink script..."
bash "$RESIZE_SCRIPT"