# Filename: grml-debootstrap
# Purpose: wrapper around debootstrap for installing plain Debian via Grml
# Authors: grml-team (grml.org), (c) Michael Prokop <mika@grml.org>
-# Bug-Reports: see http://grml.org/bugs/
+# Bug-Reports: see https://grml.org/bugs/
# License: This file is licensed under the GPL v2+
################################################################################
# variables {{{
PN="$(basename "$0")"
-if [[ -d "$(dirname "$(which "$0")")"/.git ]]; then
+if [[ -d "$(dirname "$(command -v "$0")")"/.git ]]; then
VERSION="$(git describe | sed 's|^v||')"
else
VERSION="$(dpkg-query --show --showformat='${Version}' "$PN")"
[ -n "$DEFAULT_LOCALES" ] || DEFAULT_LOCALES='en_US.UTF-8'
[ -n "$DISK_IDENTIFIER" ] || DISK_IDENTIFIER='26ada0c0-1165-4098-884d-aafd2220c2c6'
[ -n "$EXTRAPACKAGES" ] || EXTRAPACKAGES='yes'
-[ -n "$FALLBACK_MIRROR" ] || FALLBACK_MIRROR='http://httpredir.debian.org/debian'
+[ -n "$FALLBACK_MIRROR" ] || FALLBACK_MIRROR='http://deb.debian.org/debian'
[ -n "$FIXED_DISK_IDENTIFIERS" ] || FIXED_DISK_IDENTIFIERS="no"
[ -n "$FORCE" ] || FORCE=''
[ -n "$HOSTNAME" ] || HOSTNAME='grml'
[ -n "$POST_SCRIPTS" ] || POST_SCRIPTS='yes'
[ -n "$PRE_SCRIPTS" ] || PRE_SCRIPTS='yes'
[ -n "$RECONFIGURE" ] || RECONFIGURE='console-data'
-[ -n "$RELEASE" ] || RELEASE='stretch'
+[ -n "$RELEASE" ] || RELEASE='buster'
[ -n "$RM_APTCACHE" ] || RM_APTCACHE='yes'
[ -n "$SCRIPTS" ] || SCRIPTS='no' # deprecated, replaced by POST_SCRIPTS
[ -n "$SECURE" ] || SECURE='yes'
[ -n "$TUNE2FS" ] || TUNE2FS='tune2fs -c0 -i0'
[ -n "$UPGRADE_SYSTEM" ] || UPGRADE_SYSTEM='yes'
[ -n "$VMSIZE" ] || VMSIZE="2G"
+[ -n "$GRUB_INSTALL" ] || GRUB_INSTALL='yes'
# inside the chroot system locales might not be available, so use minimum:
export LANG=C
-m, --mirror <URL> Mirror which should be used for apt-get/aptitude.
-i, --iso <mnt> Mountpoint where a Debian ISO is mounted to, for use
instead of fetching packages from a mirror.
- -r, --release <name> Release of new Debian system (default: stretch).
+ -r, --release <name> Release of new Debian system (default: buster).
-t, --target <target> Target partition (/dev/...) or directory where the
system should be installed to.
-p, --mntpoint <mnt> Mountpoint used for mounting the target system,
-V, --version Show summary of options and exit.
Usage examples can be found in the grml-debootstrap manpage.
-Send bugreports to the grml-team: bugs (at) grml.org || http://grml.org/bugs/
+Send bugreports to the grml-team: bugs (at) grml.org || https://grml.org/bugs/
"
}
NORMAL='\e[0m'
einfo() {
- einfon "$1\n"
+ einfon "$1\\n"
return 0
}
}
ewarn() {
- printf " %s*%s $*\n" "${WARN}" "${NORMAL}"
+ printf " %s*%s $*\\n" "${WARN}" "${NORMAL}"
return 0
}
eerror() {
[ "${RC_ENDCOL}" != "yes" ] && [ "${LAST_E_CMD}" = "ebegin" ] && echo
- printf " %s*%s $*\n" "${BAD}" "${NORMAL}" >&2
+ printf " %s*%s $*\\n" "${BAD}" "${NORMAL}" >&2
LAST_E_CMD=eerror
return 0
}
local retval="${1:-0}"
shift
if [ "$retval" -gt 0 ]; then
- printf " %s-> Failed (rc=%s)%s\n" "${BAD}" "${retval}" "${NORMAL}"
+ printf " %s-> Failed (rc=%s)%s\\n" "${BAD}" "${retval}" "${NORMAL}"
fi
return "$retval"
}
check4progs(){
local RC=''
for arg in "$@" ; do
- which "$arg" >/dev/null 2>&1 || RC="$arg"
+ command -v "$arg" >/dev/null 2>&1 || RC="$arg"
done
if [ -n "$RC" ] ; then
echo "$RC not installed"
# ugly, but make sure we really don't leave anything (/proc /proc and
# /dev /dev are intended, trying to work around timing issues, see #657023)
- for ARG in /sys /proc /proc /dev/pts /dev/pts /dev /dev ; do
+ for ARG in /run/udev /sys /proc /proc /dev/pts /dev/pts /dev /dev ; do
[ -x "$MNTPOINT"/bin/umount ] && chroot "$MNTPOINT" umount $ARG >/dev/null 2>&1
umount "$MNTPOINT"/$ARG >/dev/null 2>&1
done
if [ -n "${ORIG_TARGET}" ] ; then
einfo "Removing loopback mount of file ${ORIG_TARGET}."
- kpartx -d "${ORIG_TARGET}" ; eend $?
+ kpartx -d "${ORIG_TARGET}"
+ # Workaround for a bug in kpartx which doesn't clean up properly,
+ # see Debian Bug #891077 and Github-PR grml/grml-debootstrap#112
+ if dmsetup ls | grep -q "^${LOOP_PART} "; then
+ kpartx -d "/dev/${LOOP_DISK}" >/dev/null
+ fi
+ eend $?
fi
}
# }}}
# make sure we have what we need {{{
-check4progs debootstrap || bailout 1
+check4progs "${DEBOOTSTRAP}" || bailout 1
# }}}
# source main configuration file {{{
# == Other options
--verbose|-v) # Increase verbosity
- if [ "$_opt_verbose" ]; then _opt_verbose=`expr $_opt_verbose + 1`
- else _opt_verbose=1; fi
+ if [ "$_opt_verbose" ]; then
+ _opt_verbose=$( _opt_verbose + 1 )
+ else
+ _opt_verbose=1
+ fi
;;
--debug) # Execute in debug mode
_opt_debug=T
bailout 1
fi
+if [ -n "$ISO" ] && [[ "$DEBOOTSTRAP" =~ mmdebstrap$ ]] ; then
+ eerror "The ISO option is incompatible with usage of mmdebstrap for bootstrapping."
+ eerror "Either drop the --iso ... option or use plain debootstrap instead."
+ eend 1
+ bailout 1
+fi
if [ "$DEBUG" = "true" ] ; then
set -x
# ask for Debian release {{{
prompt_for_release()
{
- [ -n "$RELEASE" ] && DEFAULT_RELEASE="$RELEASE" || DEFAULT_RELEASE='stretch'
+ [ -n "$RELEASE" ] && DEFAULT_RELEASE="$RELEASE" || DEFAULT_RELEASE='buster'
RELEASE="$(dialog --stdout --title "${PN}" --default-item $DEFAULT_RELEASE --menu \
"Please enter the Debian release you would like to use for installation:" \
- 0 50 5 \
+ 0 50 8 \
lenny Debian/5.0 \
squeeze Debian/6.0 \
wheezy Debian/7.0 \
jessie Debian/8.0 \
stretch Debian/9.0 \
+ buster Debian/10.0 \
+ bullseye Debian/11.0 \
sid Debian/unstable)"
[ $? -eq 0 ] || bailout
}
[ $? -eq 0 ] || bailout
if [ "$CHOOSE_MIRROR" = 'net' ] ; then
- [ -n "$MIRROR" ] || MIRROR='http://httpredir.debian.org/debian'
+ [ -n "$MIRROR" ] || MIRROR='http://deb.debian.org/debian'
MIRROR="$(dialog --stdout --title "${PN}" --inputbox \
"Please enter Debian mirror you would like to use for installing packages." \
0 0 $MIRROR)"
}
# }}}
+# format efi partition {{{
format_efi_partition() {
if [ -z "$EFI" ] ; then
return 0
fi
fi
}
+# }}}
# check for EFI support or try to enable it {{{
efi_support() {
# Support for generic release codenames is unavailable. {{{
if [ "$RELEASE" = "stable" ] || [ "$RELEASE" = "testing" ] ; then
eerror "Generic release codenames (stable, testing) are unsupported. \
-Please use specific codenames such as lenny, squeeze, wheezy, jessie or stretch." ; eend 1
+Please use specific codenames such as stretch or buster." ; eend 1
bailout 1
fi
# }}}
if [ -b "$TARGET" ] || [ -n "$VIRTUAL" ] ; then
PARTITION=1
else
+ # $TARGET was not detected as block device, but we do not want to create target directory in /dev/
+ if [[ $TARGET == "/dev/"* ]]; then
+ eerror "Error: Will not create target directory $TARGET in /dev."
+ eerror " Please check the partition(s) of the blockdevice."; eend 1
+ bailout 1
+ fi
set_target_directory
fi
# }}}
}
# }}}
+# retrieve ID_FS_UUID {{{
identify_target_uuid() {
local device="$1"
return 1
fi
}
+# }}}
+# identify TARGET_UUID {{{
mountpoint_to_blockdevice() {
TARGET_UUID=''
fi
done
}
+# }}}
# modify filesystem settings {{{
tunefs() {
bailout 1
fi
+ # make sure loop module is present and a usable loop device exists
+ modprobe -q loop
+ if ! losetup -f >/dev/null 2>&1; then
+ eerror "Error finding usable loop device" ; eend 1
+ bailout 1
+ fi
+
+ # if dm-mod isn't available then kpartx will fail with
+ # "Is device-mapper driver missing from kernel? [...]"
+ modprobe -q dm-mod
+ if ! grep -q 'device-mapper' /proc/misc >/dev/null 2>&1 ; then
+ eerror "Device-mapper support missing in kernel." ; eend 1
+ bailout 1
+ fi
+
ORIG_TARGET="$TARGET" # store for later reuse
if [ -n "$VMFILE" ]; then
einfo "Adjusting disk signature to a fixed (non-random) value"
MBRTMPFILE=$(mktemp)
dd if="${TARGET}" of="${MBRTMPFILE}" bs=512 count=1
- echo -en "\x41\x41\x41\x41" | dd of="${MBRTMPFILE}" conv=notrunc seek=440 bs=1
+ echo -en "\\x41\\x41\\x41\\x41" | dd of="${MBRTMPFILE}" conv=notrunc seek=440 bs=1
dd if="${MBRTMPFILE}" of="${TARGET}" conv=notrunc
eend $?
fi
parted -s "${TARGET}" 'mkpart primary ext4 2M -1'
parted -s "${TARGET}" 'set 1 boot on'
- # if dm-mod isn't available then kpartx will fail with
- # "Is device-mapper driver missing from kernel? [...]"
- if ! kpartx -av "$TARGET" >/dev/null 2>&1 || ! grep -q 'device-mapper' /proc/misc >/dev/null 2>&1 ; then
- einfo "Device-mapper not ready yet, trying to load dm-mod module."
- modprobe dm-mod ; eend $?
- fi
-
- # make sure loop module is present
- if ! losetup -f >/dev/null 2>&1; then
- einfo "Can not find a usable loop device, retrying after loading loop module."
- modprobe loop
- if losetup -f >/dev/null 2>&1; then
- einfo "Found a usable loop device now, continuing."
- else
- eerror "Error finding usable loop device" ; eend 1
- bailout 1
- fi
- fi
-
DEVINFO=$(kpartx -asv "$TARGET") # e.g. 'add map loop0p1 (254:5): 0 20477 linear 7:0 3'
if [ -z "${DEVINFO}" ] ; then
eerror "Error setting up loopback device." ; eend 1
# hopefully this always works as expected
LOOP_PART="${DEVINFO##add map }" # 'loop0p1 (254:5): 0 20477 linear 7:0 3'
LOOP_PART="${LOOP_PART// */}" # 'loop0p1'
+ LOOP_DISK="${LOOP_PART%p*}" # 'loop0'
export TARGET="/dev/mapper/$LOOP_PART" # '/dev/mapper/loop1p1'
if [ -z "$TARGET" ] ; then
}
# }}}
-# make VM image bootable and unmount it {{{
-finalize_vm() {
+# make VM image bootable {{{
+grub_install() {
if [ -z "${VIRTUAL}" ] ; then
return 0
fi
+ if [ "${GRUB_INSTALL}" != "yes" ] ; then
+ einfo "Not installing GRUB as requested via \$GRUB_INSTALL=$GRUB_INSTALL"
+ return 0
+ fi
if ! mount "${TARGET}" "${MNTPOINT}" ; then
eerror "Error: Mounting ${TARGET} failed, can not continue." ; eend 1
# Has chroot-script installed GRUB to MBR using grub-install (successfully), already?
# chroot-script skips installation for unset ${GRUB}
-if [[ -z "${GRUB}" ]] || ! dd if="${GRUB}" bs=512 count=1 2>/dev/null | cat -v | fgrep -q GRUB; then
+if [[ -z "${GRUB}" ]] || ! dd if="${GRUB}" bs=512 count=1 2>/dev/null | cat -v | grep -Fq GRUB; then
einfo "Installing Grub as bootloader."
if ! chroot "${MNTPOINT}" dpkg --list grub-pc 2>/dev/null | grep -q '^ii' ; then
ewarn "Please note that your system might NOT be able to properly boot."
else
einfo "Adjusting grub.cfg for successful boot sequence."
- sed -i "s;root=[^ ]\+;root=UUID=$TARGET_UUID;" "${MNTPOINT}"/boot/grub/grub.cfg
+ sed -i "s;root=[^ ]\\+;root=UUID=$TARGET_UUID;" "${MNTPOINT}"/boot/grub/grub.cfg
fi
umount "${MNTPOINT}"/proc
umount "${MNTPOINT}"/sys
umount "${MNTPOINT}"/dev/pts
try_umount 3 "${MNTPOINT}"/dev
+
+}
+# }}}
+
+# unmount VM image {{{
+umount_target() {
+ if [ -z "${VIRTUAL}" ] ; then
+ return 0
+ fi
+
umount "${MNTPOINT}"
kpartx -d "${ORIG_TARGET}" >/dev/null
+ # Workaround for a bug in kpartx which doesn't clean up properly,
+ # see Debian Bug #891077 and Github-PR grml/grml-debootstrap#112
+ if dmsetup ls | grep -q "^${LOOP_PART} "; then
+ kpartx -d "/dev/${LOOP_DISK}" >/dev/null
+ fi
}
# }}}
cp $VERBOSE -a -L "${CONFFILES}"/extrapackages/ "${MNTPOINT}"/etc/debootstrap/
- # make sure we can access network [relevant for cdebootstrap]
+ # make sure we can access network [relevant for cdebootstrap/mmdebstrap]
[ -f "${MNTPOINT}"/etc/resolv.conf ] || cp $VERBOSE /etc/resolv.conf "${MNTPOINT}"/etc/resolv.conf
# setup default locales
cp /etc/network/interfaces.examples "$MNTPOINT/etc/network/interfaces.examples"
fi
+ if [ -d /run/udev ] ; then
+ einfo "Setting up bind-mount /run/udev"
+ mkdir -p "${MNTPOINT}"/run/udev
+ mount --bind /run/udev "${MNTPOINT}"/run/udev
+ eend $?
+ fi
+
eend 0
}
# }}}
}
# }}}
+# unmount mountpoint {{{
try_umount() {
local tries=$1
local mountpoint="$2"
done
return 1 # Tried enough
}
+# }}}
# execute chroot-script {{{
chrootscript() {
fi
if grep -q "$MNTPOINT" /proc/mounts ; then
+ if mountpoint "${MNTPOINT}"/run/udev &>/dev/null ; then
+ einfo "Unmounting bind-mount /run/udev"
+ umount "${MNTPOINT}"/run/udev
+ eend $?
+ fi
+
if [ -n "$PARTITION" ] ; then
einfo "Unmount $MNTPOINT"
umount "$MNTPOINT"
for i in format_efi_partition prepare_vm mkfs tunefs \
mount_target mountpoint_to_blockdevice debootstrap_system \
preparechroot execute_pre_scripts chrootscript execute_post_scripts \
- remove_configs umount_chroot finalize_vm fscktool ; do
+ remove_configs umount_chroot grub_install umount_target fscktool ; do
if stage "${i}" ; then
if "$i" ; then
stage "${i}" 'done' && rm -f "${STAGES}/${i}"