Skip to content

Instantly share code, notes, and snippets.

@nocnokneo
Last active July 9, 2022 21:33
Show Gist options
  • Save nocnokneo/6ff81783985e28cdbd45 to your computer and use it in GitHub Desktop.
Save nocnokneo/6ff81783985e28cdbd45 to your computer and use it in GitHub Desktop.
yum-chroot.sh
#!/bin/bash
this_script=$(basename $0)
print_usage()
{
echo <<EOF
Usage: ${this_script} create CHROOT_DIR [CENTOS_RELEASE_RPM_URL]
${this_script} run CHROOT_DIR [COMMAND ...]
${this_script} --help
The first form of the command is used if CHROOT_DIR does not already exist or
is an empty directory. A new chroot will be created at CHROOT_DIR based upon
the centos-release RPM file pointed to by CENTOS_RELEASE_RPM_URL. After the
chroot is created, it will be entered using a bash login shell.
The second form of the command is used if CHROOT_DIR already exists and is not
empty. It will execute COMMAND inside the chroot. The default command is
'/bin/bash -l'
EOF
}
die()
{
echo "$1" 2>&1
exit 1
}
unmount_chroot()
{
chroot=$(readlink -e $1) || return 1
[[ ${chroot} == / ]] && return 1
chroot_mounted_dirs=$(awk -v chroot="${chroot}" '$2 ~ chroot {print $2}' /proc/mounts) || return 1
for mount_point in ${chroot_mounted_dirs}; do
echo "Unmounting ${mount_point} ..."
umount ${mount_point}
done
}
dir_is_empty()
{
[[ ! "$(find $1 -maxdepth 0 -empty)" == "" ]]
}
create_chroot()
{
( set -e
chroot_dir=$(readlink -m $1)
centos_release_rpm=${2}
if [[ ${centos_release_rpm} = *.x86_64.rpm ]]; then
basearch=x86_64
arch=x86_64
else
basearch=i386
arch=i686
fi
case "$centos_release_rpm" in
*/6*/os/i386/*)
basearch=i386
arch=i686
releasever=6
;;
*/6*/os/x86_64/*)
basearch=x86_64
arch=x86_64
releasever=6
;;
*/7*/os/x86_64/*)
basearch=x86_64
arch=x86_64
releasever=7
;;
*)
cat 1>&2 <<EOF
Unsupported RHEL release. Supported versions are:
* 6/i386
* 6/x86_64
* 7/x86_64
EOF
return 1
;;
esac
mkdir -p ${chroot_dir}
if ! dir_is_empty ${chroot_dir}; then
echo "${chroot_dir} is not empty."
read -p "Proceed anyway? [yN] " proceed
[[ $proceed = [yY] ]] || return 1
fi
rpm --root=${chroot_dir} --install --nodeps ${centos_release_rpm}
mkdir -p ${chroot_dir}/etc/yum/vars
echo ${releasever} > ${chroot_dir}/etc/yum/vars/releasever
echo ${arch} > ${chroot_dir}/etc/yum/vars/arch
echo ${basearch} > ${chroot_dir}/etc/yum/vars/basearch
yum --installroot=${chroot_dir} --assumeyes --nogpgcheck install yum
chroot ${chroot_dir} rpm --rebuilddb
)
}
run_chroot()
{
( set -e
chroot_dir=$(readlink -e $1)
shift
chroot_command="$@"
if [ -z ${chroot_command} ]; then
chroot_command="/bin/bash -l"
fi
echo "Setting up chroot and launching: ${chroot_command}"
trap "unmount_chroot \"${chroot_dir}\"" EXIT
# List of required bind mounts in order of dependency.
bind_mount_points="/proc /dev"
for mount_point in ${bind_mount_points}; do
if [ -d ${mount_point} ] && ! mount | grep -q " on ${chroot_dir}${mount_point} "; then
echo "Mounting ${chroot_dir}${mount_point} ..."
mkdir -p ${chroot_dir}${mount_point}
mount --bind ${mount_point} ${chroot_dir}${mount_point}
fi
done
cp -p /etc/resolv.conf ${chroot_dir}/etc/
touch ${chroot_dir}/root/.Xauthority
# TODO: The following is used in lieu of bind-mounting /tmp /run and /dev/pts
xauth extract - $DISPLAY | xauth -f ${chroot_dir}/root/.Xauthority merge -
chroot ${chroot_dir} env XAUTHORITY=/root/.Xauthority ${chroot_command}
echo "Exited chroot."
)
}
case "$1" in
create)
echo "Installing new chroot ..."
release_url="$3"
# Allow interactive selection if no URL provided
if [ -z "${release_url}" ]; then
url_choices='http://mirror.centos.org/centos/6/os/i386/Packages/centos-release-6-5.el6.centos.11.1.i686.rpm
http://mirror.centos.org/centos/6/os/x86_64/Packages/centos-release-6-5.el6.centos.11.1.x86_64.rpm
http://mirror.centos.org/centos/7/os/x86_64/Packages/centos-release-7-0.1406.el7.centos.2.3.x86_64.rpm'
echo -e "Select RPM URL to initialize chroot:\n"
echo "$url_choices" | awk '{ print " [", NR, "]", $0 }'
read -p "Selection: " choice
release_url=$(echo "${url_choices}" | sed -n "${choice} p")
fi
create_chroot ${2} ${release_url} || die "Failed to create chroot"
cat <<EOF
==============================================================================
New chroot created successfully. You can launch a bash session inside the
chroot with:
sudo ${this_script} run
You may wish to install the util-linux package in order to have a more
complete environment for interactive use.
==============================================================================
EOF
;;
run)
shift
run_chroot "$@" || dia "Failed to launch chroot"
;;
-h|--help)
print_usage
exit 0
;;
'')
print_usage
exit 1
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment