blob: a151002e251a708c87fbea3284d9eb0812e1aa2e (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
#!/bin/sh
#
# enter-chroot - Bind mount and chroot into installed system
# rawnix.org - https://rawnix.org
#
# Usage: enter-chroot <mountpoint>
# enter-chroot /mnt
set -e
die() { echo "ERROR: $*" >&2; exit 1; }
[ "$(id -u)" = 0 ] || die "Must root"
[ -n "$1" ] || die "Usage: enter-chroot <mountpoint>"
[ -d "$1" ] || die "Directory not found: $1"
MNT="${1%/}"
[ -n "$MNT" ] || MNT="/"
mountpoint -q "$MNT" || die "$MNT is not mounted"
[ -x "$MNT/bin/bash" ] || die "No /bin/bash in $MNT — install the core group first"
# ── Unmount on the way out ────────────────────────────────────
# Also on failure. Without a trap, a mount that fails partway
# through the list leaves the earlier ones in place and $MNT busy,
# with nothing to tell you which ones they were.
cleanup() {
umount "$MNT/sys/firmware/efi/efivars" 2>/dev/null || true
umount "$MNT/dev/pts" 2>/dev/null || true
umount "$MNT/dev/shm" 2>/dev/null || true
umount "$MNT/sys" 2>/dev/null || true
umount "$MNT/proc" 2>/dev/null || true
umount "$MNT/run" 2>/dev/null || true
umount "$MNT/tmp" 2>/dev/null || true
umount "$MNT/dev" 2>/dev/null || true
return 0
}
trap cleanup EXIT INT TERM
echo ">>> Mounting virtual filesystems..."
mount --bind /dev "$MNT/dev"
mount --bind /tmp "$MNT/tmp"
mount --bind /run "$MNT/run"
mount -t proc proc "$MNT/proc"
mount -t sysfs none "$MNT/sys"
mount -t devpts devpts "$MNT/dev/pts" -o noexec,nosuid,gid=tty,mode=0620
# `mount --bind` is not recursive, so /dev/shm does not come along
# with /dev and anything using POSIX shared memory inside the
# chroot fails with ENOENT. Mount it explicitly rather than
# switching to --rbind, which would also drag in the host's devpts
# and fight the line above.
mount -t tmpfs -o mode=1777,nosuid,nodev tmpfs "$MNT/dev/shm"
if [ -d /sys/firmware/efi ]; then
if mount -t efivarfs efivarfs "$MNT/sys/firmware/efi/efivars" 2>/dev/null; then
echo " + efivars"
else
echo " ! efivarfs unavailable - efibootmgr will not work" >&2
fi
fi
echo ">>> Entering chroot..."
echo ""
# -l, so /etc/profile is read. A non-login bash sources ~/.bashrc
# and nothing else, which means PATH, PKG_CONFIG_PATH and the rest
# of the target's /etc/profile do not apply and you silently get
# the installer's environment instead of the installed system's.
chroot "$MNT" /bin/bash -l
echo ""
echo ">>> Exited chroot. Unmounting..."
cleanup
trap - EXIT INT TERM
echo ">>> Done."
|