Содержание

rootfs

1

#!/bin/bash
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
# 06_patch_img_stretch.sh — внедрение stretch_limited в initramfs и образ .img с проверками и подтверждением
 
set -euo pipefail
[[ $EUID -ne 0 ]] && exec sudo "$0" "$@"
 
MOUNT_DIR="/mnt/imgroot"
INITRD_SCRIPT="/etc/initramfs-tools/scripts/init-premount/stretch_limited"
 
# === 📁 Поиск и выбор устройств ===
mapfile -t DEVICES < <(lsblk -nrpo NAME,SIZE,MOUNTPOINT | grep -E "/dev/sd|/dev/nvme" | awk '{print $1":"$2":"$3}')
if [[ ${#DEVICES[@]} -eq 0 ]]; then
  echo "❌ Нет доступных устройств."
  exit 1
fi
 
echo "📍 Выбери куда подключён образ .img:"
i=1
for dev in "${DEVICES[@]}"; do
  IFS=":" read -r name size mnt <<< "$dev"
  status=""
  [[ -z "$mnt" ]] && status="🔌 не примонтировано"
  echo "  $i - $name ($size) $mnt $status"
  ((i++))
done
read -rp "🔀 Выбор: " choice
[[ "$choice" == "0" || -z "$choice" ]] && echo "❎ Отменено." && exit 0
 
SEL_DEV="${DEVICES[$((choice-1))]}"
IFS=":" read -r DEV_NAME DEV_SIZE DEV_MNT <<< "$SEL_DEV"
 
if [[ -z "$DEV_MNT" ]]; then
  MNT_PATH="/mnt/rpi_target0"
  mkdir -p "$MNT_PATH"
  mount "$DEV_NAME" "$MNT_PATH"
  TARGET_DIR="$MNT_PATH"
else
  TARGET_DIR="$DEV_MNT"
fi
 
# === 📂 Поиск образов ===
mapfile -t IMG_LIST < <(find "$TARGET_DIR" -maxdepth 1 -type f -name "*.img")
if [[ ${#IMG_LIST[@]} -eq 0 ]]; then
  echo "❌ Образы .img не найдены в $TARGET_DIR"
  exit 1
fi
 
echo "📂 Образы:"
i=1
for img in "${IMG_LIST[@]}"; do
  echo "  $i - $img"
  ((i++))
done
read -rp "🔀 Выбор образа: " img_choice
[[ "$img_choice" == "0" || -z "$img_choice" ]] && echo "❎ Отменено." && exit 0
 
IMGFILE="${IMG_LIST[$((img_choice-1))]}"
 
# === Запрос лимита ===
while true; do
  read -rp "📆 Укажи лимит размера rootfs в ГБ (0 = до конца диска, по умолчанию 30): " input_limit
  if [[ -z "$input_limit" ]]; then
    read -rp "🔁 Установить 30 ГБ? [Y/n] " confirm
    if [[ "$confirm" =~ ^[Nn]$ ]]; then continue; else LIMIT_GB=30; break; fi
  elif [[ "$input_limit" =~ ^[0-9]+$ ]]; then
    LIMIT_GB="$input_limit"
    break
  else
    echo "⛔ Только целые числа, пожалуйста."
  fi
done
 
MAX_MB=$((LIMIT_GB * 1024))
 
# === Установка stretch_limited в initramfs ===
mkdir -p "$TARGET_DIR/etc/initramfs-tools/scripts/init-premount"
cat > "$TARGET_DIR$INITRD_SCRIPT" <<EOF
#!/bin/sh
PRIORITY=top
 
exec 1>>/stretch_limiter.log 2>&1
set -eux
 
echo "[initramfs] stretch_limited: запуск"
DEV="/dev/mmcblk0"
PART="\${DEV}p2"
FLAG_FILE="/etc/.stretch_done"
MAX_MB=$MAX_MB
 
if [ -f "\$FLAG_FILE" ]; then
  echo "Файл stretch_done найден. Выход."
  exit 0
fi
 
START=\$(fdisk -l "\$DEV" | awk '/mmcblk0p2/ {print \$2}')
END=\$(fdisk -l "\$DEV" | awk '/mmcblk0p2/ {print \$3}')
SECTOR_SIZE=\$(blockdev --getss "\$DEV")
CURRENT_MB=\$(( (END - START + 1) * SECTOR_SIZE / 1024 / 1024 ))
 
echo "Текущий размер: \$CURRENT_MB MB, лимит: \$MAX_MB MB"
 
if [ "\$CURRENT_MB" -le "\$MAX_MB" ]; then
  echo "Уже в пределах лимита."
  touch "\$FLAG_FILE"
  exit 0
fi
 
echo "Изменение раздела..."
parted -s "\$DEV" resizepart 2 "\${MAX_MB}MB"
partprobe "\$DEV"
sleep 2
resize2fs "\$PART"
touch "\$FLAG_FILE"
echo "✅ Готово"
EOF
 
chmod +x "$TARGET_DIR$INITRD_SCRIPT"
 
chroot "$TARGET_DIR" update-initramfs -u
ln -sf /boot/initrd.img-$(uname -r) "$TARGET_DIR/boot/initrd.img"
 
echo "✅ stretch_limited установлен в initramfs и образ. Будет выполнен при загрузке до монтирования rootfs."

2

Проверка

lsinitramfs /boot/initrd.img-$(uname -r) | grep stretch_limited
lsinitramfs /boot/initrd.img-$(uname -r) -l | grep stretch_limited &&
lsinitramfs /boot/initrd.img-$(uname -r) | grep -q "stretch_limited" && echo "✅ Есть в initramfs"
cat /boot/stretch_limiter.log
df -h /