347 lines
9.3 KiB
Bash
347 lines
9.3 KiB
Bash
#!/bin/bash
|
|
# migrace.sh - Přesun Arch Linuxu z nvme1n1 na nvme0n1
|
|
# Autor: pro Archose, v1.0 (2026-04)
|
|
#
|
|
# Spouštěj z live USB prostředí (Arch ISO).
|
|
# NIKDY ne z běžícího systému, který chceš migrovat.
|
|
|
|
set -e # padni při první chybě
|
|
set -u # padni při nedefinované proměnné
|
|
|
|
# ======== BAREVNÉ VÝSTUPY ========
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
log() { echo -e "${BLUE}[INFO]${NC} $*"; }
|
|
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
|
err() { echo -e "${RED}[ERR]${NC} $*" >&2; }
|
|
|
|
# ======== KONFIGURACE ========
|
|
SRC_DISK="/dev/nvme1n1" # stávající systém
|
|
SRC_BOOT="${SRC_DISK}p1"
|
|
SRC_ROOT="${SRC_DISK}p2"
|
|
SRC_HOME="${SRC_DISK}p3"
|
|
|
|
DST_DISK="/dev/nvme0n1" # cíl
|
|
DST_BOOT="${DST_DISK}p1"
|
|
DST_ROOT="${DST_DISK}p2"
|
|
DST_HOME="${DST_DISK}p3"
|
|
|
|
ROOT_SIZE_GB=150
|
|
BOOT_SIZE_MB=1024
|
|
|
|
MNT_OLD="/mnt/old"
|
|
MNT_NEW="/mnt/new"
|
|
|
|
LOG_FILE="/tmp/migrace-$(date +%Y%m%d-%H%M%S).log"
|
|
|
|
# ======== POMOCNÉ FUNKCE ========
|
|
|
|
confirm() {
|
|
local msg="$1"
|
|
echo
|
|
echo -e "${YELLOW}>>> $msg${NC}"
|
|
read -rp "Pokračovat? (ano/NE): " odp
|
|
if [[ "$odp" != "ano" ]]; then
|
|
err "Zrušeno uživatelem."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
check_root() {
|
|
if [[ $EUID -ne 0 ]]; then
|
|
err "Spusť jako root (sudo bash migrace.sh)"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
check_live_env() {
|
|
# Pokud je /dev/nvme1n1p2 mountnutý jako /, tak jsme v běžícím systému
|
|
if findmnt -n -o SOURCE / | grep -q "nvme1n1p2"; then
|
|
err "Běžíš z nvme1n1p2, kterou chceš migrovat!"
|
|
err "Tohle MUSÍ běžet z live USB prostředí."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
check_disks() {
|
|
for d in "$SRC_DISK" "$DST_DISK"; do
|
|
if [[ ! -b "$d" ]]; then
|
|
err "Disk $d neexistuje!"
|
|
exit 1
|
|
fi
|
|
done
|
|
log "Zdroj: $SRC_DISK ($(lsblk -dno SIZE $SRC_DISK))"
|
|
log "Cíl: $DST_DISK ($(lsblk -dno SIZE $DST_DISK))"
|
|
}
|
|
|
|
# ======== KROKY ========
|
|
|
|
step_01_info() {
|
|
clear
|
|
cat <<EOF
|
|
╔═══════════════════════════════════════════════════════════════╗
|
|
║ MIGRACE ARCH LINUXU: nvme1n1 → nvme0n1 ║
|
|
╚═══════════════════════════════════════════════════════════════╝
|
|
|
|
Plán:
|
|
1. Přerozdělit $DST_DISK (${ROOT_SIZE_GB} GB root + zbytek home + 1 GB EFI)
|
|
2. Mkfs nových oddílů (ext4 + fat32)
|
|
3. Rsync /, /boot, /home ze $SRC_DISK na $DST_DISK
|
|
4. Upravit fstab a systemd-boot entry na novém systému
|
|
5. Chroot a bootctl install
|
|
6. Umount a reboot
|
|
|
|
Log: $LOG_FILE
|
|
|
|
Stávající stav:
|
|
EOF
|
|
lsblk -o NAME,SIZE,FSTYPE,LABEL,MOUNTPOINTS "$SRC_DISK" "$DST_DISK"
|
|
echo
|
|
|
|
confirm "Potvrzuješ výše uvedený plán?"
|
|
}
|
|
|
|
step_02_partition() {
|
|
log "Krok 2: Přerozdělení $DST_DISK"
|
|
echo
|
|
warn "VŠECHNA DATA NA $DST_DISK BUDOU SMAZÁNA!"
|
|
echo "Aktuálně na $DST_DISK:"
|
|
lsblk -o NAME,SIZE,FSTYPE,LABEL "$DST_DISK"
|
|
confirm "Smazat $DST_DISK a udělat nové oddíly?"
|
|
|
|
log "Mažu staré oddíly..."
|
|
wipefs -a "$DST_DISK"
|
|
sgdisk --zap-all "$DST_DISK"
|
|
|
|
log "Vytvářím nové oddíly..."
|
|
sgdisk -n 1:0:+${BOOT_SIZE_MB}M -t 1:ef00 -c 1:"EFI" "$DST_DISK"
|
|
sgdisk -n 2:0:+${ROOT_SIZE_GB}G -t 2:8300 -c 2:"arch_root" "$DST_DISK"
|
|
sgdisk -n 3:0:0 -t 3:8300 -c 3:"arch_home" "$DST_DISK"
|
|
|
|
partprobe "$DST_DISK"
|
|
sleep 2
|
|
|
|
ok "Nové rozdělení:"
|
|
lsblk -o NAME,SIZE,FSTYPE,LABEL "$DST_DISK"
|
|
}
|
|
|
|
step_03_mkfs() {
|
|
log "Krok 3: Formátování"
|
|
confirm "Formátovat $DST_BOOT (FAT32), $DST_ROOT (ext4), $DST_HOME (ext4)?"
|
|
|
|
mkfs.fat -F32 -n EFI "$DST_BOOT"
|
|
mkfs.ext4 -F -L arch_root "$DST_ROOT"
|
|
mkfs.ext4 -F -L arch_home "$DST_HOME"
|
|
|
|
ok "Formátováno."
|
|
}
|
|
|
|
step_04_mount() {
|
|
log "Krok 4: Mount"
|
|
|
|
mkdir -p "$MNT_NEW" "$MNT_OLD"
|
|
|
|
# Cíl
|
|
mount "$DST_ROOT" "$MNT_NEW"
|
|
mkdir -p "$MNT_NEW/boot" "$MNT_NEW/home"
|
|
mount "$DST_BOOT" "$MNT_NEW/boot"
|
|
mount "$DST_HOME" "$MNT_NEW/home"
|
|
|
|
# Zdroj (read-only!)
|
|
mount -o ro "$SRC_ROOT" "$MNT_OLD"
|
|
mkdir -p "$MNT_OLD/boot" "$MNT_OLD/home"
|
|
mount -o ro "$SRC_BOOT" "$MNT_OLD/boot"
|
|
mount -o ro "$SRC_HOME" "$MNT_OLD/home"
|
|
|
|
ok "Namountováno:"
|
|
mount | grep -E "$MNT_NEW|$MNT_OLD"
|
|
}
|
|
|
|
step_05_rsync_root() {
|
|
log "Krok 5a: Rsync / (bez /boot, /home, virtuálních FS)"
|
|
confirm "Spustit rsync root (rychlé, cca 5 min)?"
|
|
|
|
rsync -aAXHv --info=progress2 \
|
|
--exclude='/boot/*' \
|
|
--exclude='/home/*' \
|
|
--exclude='/dev/*' \
|
|
--exclude='/proc/*' \
|
|
--exclude='/sys/*' \
|
|
--exclude='/tmp/*' \
|
|
--exclude='/run/*' \
|
|
--exclude='/mnt/*' \
|
|
--exclude='/media/*' \
|
|
--exclude='/lost+found' \
|
|
"$MNT_OLD/" "$MNT_NEW/"
|
|
|
|
ok "Rsync root hotov."
|
|
}
|
|
|
|
step_06_rsync_boot() {
|
|
log "Krok 5b: Rsync /boot"
|
|
rsync -aAXHv --info=progress2 "$MNT_OLD/boot/" "$MNT_NEW/boot/"
|
|
ok "Rsync boot hotov."
|
|
}
|
|
|
|
step_07_rsync_home() {
|
|
log "Krok 5c: Rsync /home (cca 600 GB, 20-40 minut)"
|
|
confirm "Spustit rsync home?"
|
|
rsync -aAXHv --info=progress2 "$MNT_OLD/home/" "$MNT_NEW/home/"
|
|
ok "Rsync home hotov."
|
|
}
|
|
|
|
step_08_update_fstab() {
|
|
log "Krok 6: Úprava fstab"
|
|
|
|
local new_root_uuid new_boot_uuid new_home_uuid
|
|
new_root_uuid=$(blkid -s UUID -o value "$DST_ROOT")
|
|
new_boot_uuid=$(blkid -s UUID -o value "$DST_BOOT")
|
|
new_home_uuid=$(blkid -s UUID -o value "$DST_HOME")
|
|
|
|
log "Nové UUID:"
|
|
log " root ($DST_ROOT): $new_root_uuid"
|
|
log " boot ($DST_BOOT): $new_boot_uuid"
|
|
log " home ($DST_HOME): $new_home_uuid"
|
|
|
|
# Záloha starého fstab
|
|
cp "$MNT_NEW/etc/fstab" "$MNT_NEW/etc/fstab.pred-migraci"
|
|
|
|
cat > "$MNT_NEW/etc/fstab" <<EOF
|
|
# Migrace na nvme0n1 - $(date)
|
|
# Záloha původního: /etc/fstab.pred-migraci
|
|
|
|
# /dev/nvme0n1p2 - root
|
|
UUID=$new_root_uuid / ext4 rw,relatime 0 1
|
|
|
|
# /dev/nvme0n1p1 - boot (EFI)
|
|
UUID=$new_boot_uuid /boot vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro 0 2
|
|
|
|
# /dev/nvme0n1p3 - home
|
|
UUID=$new_home_uuid /home ext4 rw,relatime 0 2
|
|
|
|
# Datový šifrovaný disk (beze změny)
|
|
/dev/mapper/data_crypt /mnt/data ext4 defaults 0 2
|
|
EOF
|
|
|
|
ok "Nový fstab:"
|
|
cat "$MNT_NEW/etc/fstab"
|
|
}
|
|
|
|
step_09_update_boot_entry() {
|
|
log "Krok 7: Úprava systemd-boot entry"
|
|
|
|
local new_root_partuuid
|
|
new_root_partuuid=$(blkid -s PARTUUID -o value "$DST_ROOT")
|
|
log "Nový PARTUUID root: $new_root_partuuid"
|
|
|
|
local entry_file
|
|
entry_file=$(ls "$MNT_NEW/boot/loader/entries/"*.conf | head -1)
|
|
|
|
if [[ -z "$entry_file" ]]; then
|
|
err "Nenašel jsem boot entry v $MNT_NEW/boot/loader/entries/"
|
|
exit 1
|
|
fi
|
|
|
|
# Záloha
|
|
cp "$entry_file" "${entry_file}.pred-migraci"
|
|
|
|
# Nahrazení PARTUUID
|
|
sed -i -E "s|PARTUUID=[a-f0-9-]+|PARTUUID=$new_root_partuuid|" "$entry_file"
|
|
|
|
ok "Nová boot entry ($entry_file):"
|
|
cat "$entry_file"
|
|
}
|
|
|
|
step_10_chroot_bootctl() {
|
|
log "Krok 8: Chroot + bootctl install + mkinitcpio"
|
|
confirm "Spustit bootctl install a mkinitcpio v chroot?"
|
|
|
|
# Příprava chrootu
|
|
for fs in dev proc sys run; do
|
|
mount --rbind /$fs "$MNT_NEW/$fs"
|
|
mount --make-rslave "$MNT_NEW/$fs"
|
|
done
|
|
mount --bind /sys/firmware/efi/efivars "$MNT_NEW/sys/firmware/efi/efivars" || true
|
|
|
|
chroot "$MNT_NEW" /bin/bash <<'CHROOT_EOF'
|
|
set -e
|
|
echo ">>> bootctl install..."
|
|
bootctl --path=/boot install
|
|
|
|
echo ">>> mkinitcpio -P..."
|
|
mkinitcpio -P
|
|
|
|
echo ">>> bootctl status:"
|
|
bootctl status || true
|
|
|
|
echo ">>> Hotovo v chroot."
|
|
CHROOT_EOF
|
|
|
|
ok "Chroot dokončen."
|
|
}
|
|
|
|
step_11_umount() {
|
|
log "Krok 9: Umount"
|
|
|
|
umount -R "$MNT_NEW" || true
|
|
umount -R "$MNT_OLD" || true
|
|
|
|
ok "Odpojeno."
|
|
}
|
|
|
|
step_12_final() {
|
|
cat <<EOF
|
|
|
|
╔═══════════════════════════════════════════════════════════════╗
|
|
║ HOTOVO ║
|
|
╚═══════════════════════════════════════════════════════════════╝
|
|
|
|
Co dál:
|
|
1. reboot
|
|
2. V BIOSu nastav boot priority: $DST_DISK PŘED $SRC_DISK
|
|
(nebo stiskni boot menu klávesu při startu - F8/F11/F12)
|
|
3. Až nabootuje nový systém, ověř:
|
|
df -hT / # mělo by být $DST_ROOT
|
|
lsblk
|
|
bootctl status
|
|
|
|
4. NECHEJ STARÝ $SRC_DISK NA POKOJI minimálně týden!
|
|
Kdyby cokoliv, boothneš do něj a můžeš opravit.
|
|
|
|
5. Až budeš jistý, můžeš $SRC_DISK použít na cokoliv:
|
|
sudo cfdisk $SRC_DISK
|
|
|
|
Log uložen v: $LOG_FILE
|
|
EOF
|
|
}
|
|
|
|
# ======== MAIN ========
|
|
|
|
main() {
|
|
check_root
|
|
check_live_env
|
|
check_disks
|
|
|
|
exec > >(tee -a "$LOG_FILE") 2>&1
|
|
|
|
step_01_info
|
|
step_02_partition
|
|
step_03_mkfs
|
|
step_04_mount
|
|
step_05_rsync_root
|
|
step_06_rsync_boot
|
|
step_07_rsync_home
|
|
step_08_update_fstab
|
|
step_09_update_boot_entry
|
|
step_10_chroot_bootctl
|
|
step_11_umount
|
|
step_12_final
|
|
}
|
|
|
|
main "$@"
|