It is a known bug with the programming language. 🙂
#GeekyJokes #ProgrammerHumor
It is a known bug with the programming language. 🙂
#GeekyJokes #ProgrammerHumor
Containers are all the rage right now and rightfully so – not only do they help abstract away some of the complexity and dependencies of your apps and solutions, they also make managing of environments, and, deployments much simpler. And the fact that you can do it in a consistent, and repeatable fashion is just icing on the cake.
As a simple example, with Docker, on Windows (as in my case), I can run a dockerized app, on a different OS than the host, which can also be interactive.
The command below will spawn a container, pull down the image of Ubuntu and then run an interactive terminal, tying the terminal to the standard input. Of course in this example, this requires that you already have Docker installed (the Community Edition would be just fine to play around with).
docker run --interactive --tty ubuntu bash
Now, with Docker if you do get the following error (on Windows): “Error response from daemon: operating system on which parent image was created is not Windows.” as also shown below, the way to fix it is to switch on Experimental features.
To try and fix this, right click on the docker icon in the system tray, choose Settings, and from the setting screen, in the Daemon tab, enable experimental features as shown below.
And after enabling the experimental features, the docker daemon will restart. And post that, if you run the docker command again, it would work as expected:
This is just the beginning, there of course is a lot more to it. 🙂
I am writing this on a Microsoft Surface Book, running Ubuntu natively, and there isn’t any Windows option – I blew away, the Windows partition, and there isn’t any other OS on it.
Why, some of you might think? Well, why not. 🙂 For me the motive is two fold: one am a geek and love to hack what works and cannot work – how else will one learn? And two, explore and see which AI frameworks, tools, and runtimes works better on Linux natively
Well I must say, this experiment has been a pleasant surprise and much more successful that I originally thought of. Most of the things are working quite well on Surface with Ubuntu – including touch and pen (both seem like mouse clicks). As the screenshot below shows, Ubuntu is running quite nicely – including most of the features. There are a few things that quite don’t – I have them listed later in the post.
So much so, that Visual Studio code is running natively and whilst I haven’t had a chance to use it much (yet), that fact that it can even so much was something I wasn’t expecting without running some containers or VM’s or the likes.
So, how does one go about doing this? It is quite simple these days to be honest. Below are the steps I had followed. I do think the real magic is the hard work that JakeDay has done to get the kernel and firmware supported.
Disclaimer: My experience outlined here is related to the Surface Book – it can also run and be supported on other Surface devices, and the exact nature of what works or doesn’t work would be a little different.
Change boot kernel: Finally, after you have rebooted, the odds of Ubuntu booting off the ‘right’ kernel is quite slim and best to manually pick this. You can of course use the grub, or what I find better – install the grub customizer, and then choose the correct option as shown below. Once picked and you had hit save, you also need to run the following in a terminal to make these persist: sudo update-grub
And that is all to it for getting the base install and customization running.
If you are super curious on what that setup script does, the code is below (also listed on github). What is interesting to see the various hardware models supported.
LX_BASE="" LX_VERSION="" if [ -r /etc/os-release ]; then . /etc/os-release if [ $ID = arch ]; then LX_BASE=$ID elif [ $ID = ubuntu ]; then LX_BASE=$ID LX_VERSION=$VERSION_ID elif [ ! -z "$UBUNTU_CODENAME" ] ; then LX_BASE="ubuntu" LX_VERSION=$VERSION_ID else LX_BASE=$ID LX_VERSION=$VERSION fi else echo "Could not identify your distro. Please open script and run commands manually." exit fi SUR_MODEL="$(dmidecode | grep "Product Name" -m 1 | xargs | sed -e 's/Product Name: //g')" SUR_SKU="$(dmidecode | grep "SKU Number" -m 1 | xargs | sed -e 's/SKU Number: //g')" echo "\nRunning $LX_BASE version $LX_VERSION on a $SUR_MODEL.\n" read -rp "Press enter if this is correct, or CTRL-C to cancel." cont;echo echo "\nContinuing setup...\n" echo "Coping the config files under root to where they belong...\n" cp -Rb root/* / echo "Making /lib/systemd/system-sleep/sleep executable...\n" chmod a+x /lib/systemd/system-sleep/sleep read -rp "Do you want to replace suspend with hibernate? (type yes or no) " usehibernate;echo if [ "$usehibernate" = "yes" ]; then if [ "$LX_BASE" = "ubuntu" ] && [ 1 -eq "$(echo "${LX_VERSION} >= 17.10" | bc)" ]; then echo "Using Hibernate instead of Suspend...\n" ln -sfb /lib/systemd/system/hibernate.target /etc/systemd/system/suspend.target && sudo ln -sfb /lib/systemd/system/systemd-hibernate.service /etc/systemd/system/systemd-suspend.service else echo "Using Hibernate instead of Suspend...\n" ln -sfb /usr/lib/systemd/system/hibernate.target /etc/systemd/system/suspend.target && sudo ln -sfb /usr/lib/systemd/system/systemd-hibernate.service /etc/systemd/system/systemd-suspend.service fi else echo "Not touching Suspend\n" fi read -rp "Do you want use the patched libwacom packages? (type yes or no) " uselibwacom;echo if [ "$uselibwacom" = "yes" ]; then echo "Installing patched libwacom packages..." dpkg -i packages/libwacom/*.deb apt-mark hold libwacom else echo "Not touching libwacom" fi if [ "$SUR_MODEL" = "Surface Pro 3" ]; then echo "\nInstalling i915 firmware for Surface Pro 3...\n" mkdir -p /lib/firmware/i915 unzip -o firmware/i915_firmware_bxt.zip -d /lib/firmware/i915/ fi if [ "$SUR_MODEL" = "Surface Pro" ]; then echo "\nInstalling IPTS firmware for Surface Pro 2017...\n" mkdir -p /lib/firmware/intel/ipts unzip -o firmware/ipts_firmware_v102.zip -d /lib/firmware/intel/ipts/ echo "\nInstalling i915 firmware for Surface Pro 2017...\n" mkdir -p /lib/firmware/i915 unzip -o firmware/i915_firmware_kbl.zip -d /lib/firmware/i915/ fi if [ "$SUR_MODEL" = "Surface Pro 4" ]; then echo "\nInstalling IPTS firmware for Surface Pro 4...\n" mkdir -p /lib/firmware/intel/ipts unzip -o firmware/ipts_firmware_v78.zip -d /lib/firmware/intel/ipts/ echo "\nInstalling i915 firmware for Surface Pro 4...\n" mkdir -p /lib/firmware/i915 unzip -o firmware/i915_firmware_skl.zip -d /lib/firmware/i915/ fi if [ "$SUR_MODEL" = "Surface Pro 2017" ]; then echo "\nInstalling IPTS firmware for Surface Pro 2017...\n" mkdir -p /lib/firmware/intel/ipts unzip -o firmware/ipts_firmware_v102.zip -d /lib/firmware/intel/ipts/ echo "\nInstalling i915 firmware for Surface Pro 2017...\n" mkdir -p /lib/firmware/i915 unzip -o firmware/i915_firmware_kbl.zip -d /lib/firmware/i915/ fi if [ "$SUR_MODEL" = "Surface Pro 6" ]; then echo "\nInstalling IPTS firmware for Surface Pro 6...\n" mkdir -p /lib/firmware/intel/ipts unzip -o firmware/ipts_firmware_v102.zip -d /lib/firmware/intel/ipts/ echo "\nInstalling i915 firmware for Surface Pro 6...\n" mkdir -p /lib/firmware/i915 unzip -o firmware/i915_firmware_kbl.zip -d /lib/firmware/i915/ fi if [ "$SUR_MODEL" = "Surface Laptop" ]; then echo "\nInstalling IPTS firmware for Surface Laptop...\n" mkdir -p /lib/firmware/intel/ipts unzip -o firmware/ipts_firmware_v79.zip -d /lib/firmware/intel/ipts/ echo "\nInstalling i915 firmware for Surface Laptop...\n" mkdir -p /lib/firmware/i915 unzip -o firmware/i915_firmware_skl.zip -d /lib/firmware/i915/ fi if [ "$SUR_MODEL" = "Surface Book" ]; then echo "\nInstalling IPTS firmware for Surface Book...\n" mkdir -p /lib/firmware/intel/ipts unzip -o firmware/ipts_firmware_v76.zip -d /lib/firmware/intel/ipts/ echo "\nInstalling i915 firmware for Surface Book...\n" mkdir -p /lib/firmware/i915 unzip -o firmware/i915_firmware_skl.zip -d /lib/firmware/i915/ fi if [ "$SUR_MODEL" = "Surface Book 2" ]; then echo "\nInstalling IPTS firmware for Surface Book 2...\n" mkdir -p /lib/firmware/intel/ipts if [ "$SUR_SKU" = "Surface_Book_1793" ]; then unzip -o firmware/ipts_firmware_v101.zip -d /lib/firmware/intel/ipts/ else unzip -o firmware/ipts_firmware_v137.zip -d /lib/firmware/intel/ipts/ fi echo "\nInstalling i915 firmware for Surface Book 2...\n" mkdir -p /lib/firmware/i915 unzip -o firmware/i915_firmware_kbl.zip -d /lib/firmware/i915/ echo "\nInstalling nvidia firmware for Surface Book 2...\n" mkdir -p /lib/firmware/nvidia/gp108 unzip -o firmware/nvidia_firmware_gp108.zip -d /lib/firmware/nvidia/gp108/ fi if [ "$SUR_MODEL" = "Surface Go" ]; then echo "\nInstalling ath10k firmware for Surface Go...\n" mkdir -p /lib/firmware/ath10k unzip -o firmware/ath10k_firmware.zip -d /lib/firmware/ath10k/ fi echo "Installing marvell firmware...\n" mkdir -p /lib/firmware/mrvl/ unzip -o firmware/mrvl_firmware.zip -d /lib/firmware/mrvl/ read -rp "Do you want to set your clock to local time instead of UTC? This fixes issues when dual booting with Windows. (type yes or no) " uselocaltime;echo if [ "$uselocaltime" = "yes" ]; then echo "Setting clock to local time...\n" timedatectl set-local-rtc 1 hwclock --systohc --localtime else echo "Not setting clock" fi read -rp "Do you want this script to download and install the latest kernel for you? (type yes or no) " autoinstallkernel;echo if [ "$autoinstallkernel" = "yes" ]; then echo "Downloading latest kernel...\n" urls=$(curl --silent "https://api.github.com/repos/jakeday/linux-surface/releases/latest" | grep '"browser_download_url":' | sed -E 's/.*"([^"]+)".*/\1/') resp=$(wget -P tmp $urls) echo "Installing latest kernel...\n" dpkg -i tmp/*.deb rm -rf tmp else echo "Not downloading latest kernel" fi echo "\nAll done! Please reboot."
Lastly, below are the things not working for me – none of these are deal breakers but something to be aware of.
Happy hacking!