Last active
October 2, 2022 12:48
-
-
Save JoshuaWierenga/ad1c8c4fd4c7c6f5b362d6cf400b0435 to your computer and use it in GitHub Desktop.
Script for Ubuntu 22.04 WSL2 to setup qemu user mode emulation for a different archecture using cloud images
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /bin/sh | |
# Ubuntu 22.04 WSL2 qemu user mode emulation setup 0.4.0 | |
version="0.4.0" | |
usage() | |
{ | |
echo "Ubuntu 22.04 WSL2 qemu user mode emulation setup $version | |
Usage: $0 [general and mode specific flags] [-i or -e] architecture | |
General Flags: | |
-?, -h: Display this usage information and then quit. | |
-v: Display version history and then quit. | |
-d Specify directory to use for install or access modes. Defaults to ubuntu{architecture} for install mode only. | |
Modes: | |
-i: Install new architecture to specified folder. | |
architecture: Specifies which architecture to install, tested architectures are amd64, arm64, s390x and riscv64, others may work. | |
optional directory defaults to ubuntu{architecture} if not given. | |
-e: Chroot into already installed architecture. | |
architecture: Specifies which architecture the required directory argument is for. | |
Install(-i) specific flags: | |
-a: Avoid wsl images for amd64 and arm64, use general cloud images instead." | |
exit | |
} | |
version() | |
{ | |
echo "Ubuntu 22.04 WSL2 qemu user mode emulation setup $version | |
Change log: | |
Changes in 0.4.0: | |
Added support for accessing existing chroot via -e flag. | |
Added directory flag -d which can be used to override the install path when using -i, is also required when using -e. | |
Changes in 0.3.0: | |
Cleaned up usage info. | |
Moved default install action to -i flag. | |
Changes in 0.2.0: | |
Improved optional parameter handling. | |
Added version info. | |
Fixed amd64 and arm64 image downloading and finding qemu binary when -a is provided. | |
Fixed non wsl image extracting." | |
exit | |
} | |
# Helpers | |
checkAction() | |
{ | |
if [ -n "$action" ] ; then | |
echo "Only one of -i and -e can be provided." | |
usage | |
fi | |
} | |
getQemuStaticName() | |
{ | |
# TODO Find better method since qemu has ppc64le while ubuntu has ppc64el which are the same thing | |
amd64QemuPathArch="x86_64" | |
arm64QemuPathArch="aarch64" | |
qemuStaticNamePrefix="qemu-" | |
qemuStaticNameSuffix="-static" | |
if [ "$1" = amd64 ] ; then | |
qemuStaticArch=$amd64QemuPathArch | |
elif [ "$1" = arm64 ] ; then | |
qemuStaticArch=$arm64QemuPathArch | |
else | |
qemuStaticArch="$1" | |
fi | |
qemuStaticName=$qemuStaticNamePrefix$qemuStaticArch$qemuStaticNameSuffix | |
} | |
# Based on https://serverfault.com/a/901858 | |
handleMountBind() | |
{ | |
if ! findmnt "$2" >/dev/null ; then | |
sudo mount -o bind "$1" "$2" | |
fi | |
} | |
# Modes | |
# Based on https://github.com/Biswa96/WSLInstall/blob/master/docs/Chroot_ARM64_Linux_Distro.md | |
setupArchChroot() | |
{ | |
baseUrl="https://cloud-images.ubuntu.com/releases/22.04/release/" | |
amd64Url="ubuntu-22.04-server-cloudimg-amd64-wsl.rootfs.tar.gz" | |
arm64Url="ubuntu-22.04-server-cloudimg-arm64-wsl.rootfs.tar.gz" | |
generalUrlPrefix="ubuntu-22.04-server-cloudimg-" | |
generalUrlSuffix="-root.tar.xz" | |
if [ -z "$avoidWSLImages" ] && [ "$architecture" = amd64 ] ; then | |
imageName=$amd64Url | |
elif [ -z "$avoidWSLImages" ] && [ "$architecture" = arm64 ] ; then | |
imageName=$arm64Url | |
else | |
imageName=$generalUrlPrefix$architecture$generalUrlSuffix | |
fi | |
url=$baseUrl$imageName | |
getQemuStaticName "$architecture" | |
httpCode=$(curl -I -s "$url" -o /dev/null -w "%{http_code}\n") | |
if [ "$httpCode" -ne 200 ] ; then | |
echo "Error finding ubuntu cloud image, this could be because the site couldn't be reached, the images have been moved or no image exists for the $architecture architecture." | |
exit | |
fi | |
sudo apt install -y \ | |
binfmt-support \ | |
daemonize \ | |
qemu-user-static | |
# TODO Allow specifying destination | |
installPath=ubuntu"$architecture" | |
# TODO Prompt user before continuing as this may override stuff otherwise | |
if [ ! -d "$installPath" ] ; then | |
mkdir "$installPath" | |
fi | |
wget -N "$url" | |
sudo tar -xaf "$imageName" -C "$installPath" | |
# TODO: Avoid multiple instances using -l? | |
sudo daemonize \ | |
/usr/bin/unshare -fp --mount-proc \ | |
/lib/systemd/systemd --system-unit=basic.target | |
sudo cp /usr/bin/"$qemuStaticName" "$installPath"/usr/bin | |
sudo mount -o bind /proc "$installPath"/proc | |
sudo mount -o bind /dev "$installPath"/dev | |
# Attempt to fix issues with the following user setup just giving a bunch of errors if ran too early | |
sleep 1 | |
# Based on https://stackoverflow.com/a/51312156 | |
# TODO Allow specifying username and password | |
sudo chroot "$installPath" "$qemuStaticName" bin/bash << "EOT" | |
adduser --gecos "" --disabled-password test | |
chpasswd <<<"test:test" | |
usermod -aG sudo test | |
EOT | |
# TODO Fix networking | |
# TODO Fix pty allocation | |
} | |
enterArchChroot() | |
{ | |
if [ -z "$directory" ] ; then | |
echo "Entering a chroot with -e requires the -d directory flag is provided as well." | |
usage | |
fi | |
# TODO Confirm that $directory contains an install made using setupArchChroot | |
# TODO Figure out based on copy installed to $directory/usr/bin | |
getQemuStaticName "$architecture" | |
# TODO: Avoid multiple instances using -l? | |
sudo daemonize \ | |
/usr/bin/unshare -fp --mount-proc \ | |
/lib/systemd/systemd --system-unit=basic.target | |
handleMountBind /dev "$directory"/dev | |
handleMountBind /proc "$directory"/proc | |
sudo chroot "$directory" "$qemuStaticName" bin/su - test | |
} | |
# based on https://www.shellscript.sh/tips/getopts/ | |
unset avoidWSLImages directory action | |
while getopts "a?hvd:i:e:" c ; do | |
case $c in | |
a) avoidWSLImages=1 ;; | |
h|\?) usage ;; | |
v) version ;; | |
d) directory=$OPTARG ;; | |
i) checkAction | |
action="install" ; | |
architecture=$OPTARG ;; | |
e) checkAction | |
action="enter" ; | |
architecture=$OPTARG ;; | |
esac | |
done | |
if [ -z $action ] ; then | |
usage ; | |
elif [ $action = install ] ; then | |
setupArchChroot | |
elif [ $action = enter ] ; then | |
enterArchChroot | |
fi | |
# TODO Add options to unmount and delete chroot environment |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment