Future-proof your skills with Linux, Python, vim & git as I share with you the most timeless and love-worthy tools in tech through my two great projects that work great together.

Rappelling Down The Rabbit Hole: A Linux Script Adventure

I dive deep into the depths of Windows bat scripts and Linux bash scripts in this one, turning a filename into an optional input parameter so you can choose what version of Python to install. I also get a lot of help from Copilot along the way, and sort long-standing issues with WSL's systemd feature not working as expected by tweaking both a .wslconfig and a .wslconf file.

Ready, Set, Rappel: My Linux Script Adventure Begins!

By Michael Levin

Thursday, May 11, 2023

Make sure your modified Linux DrinkMe install is working, and get ready to cut some catapult ropes. The metaphor is strong and the path is clear. You’re at the top of the search results for both Levinux and Pipulate, and you can use either s homepage to initiate the process. 1, 2, 3… 1?

Whoah, it really is an eye opener what Copilot can do for me in these install.bat and install.sh files. First, I’m going right for the jugular in fixing the last thing that seems to be keeping the updated procedure from working. I moved both the all and startjupyter scripts out of /usr/local/sbin and into /home/ubuntu/pyenv/bin/. Because of that, the owner of the file needs to be ubuntu and not root in order for the JupyterLab systemd service to start. I’m testing that now.

Most people aren’t going to get this whole thing until it’s somewhat world-changing. And now with Copilot to enhance my ability, it’s accelerating the process. There’s a very big prize here for the first person to popularize a generic Linux VM that can be installed on any computer, and then have it host a popular app, one that aligns with some very nice keywords and also serves the purpose of my employer.

If this works, do a fast pass at the easy-pickings optimizations. And then silence as much of the output as possible. That’s kind of the kiss of death about this project to many people. The Ubuntu apt updates and upgrades are going to intimidate the heck out of people. I like it because it’s like Alice falling down the rabbit hole, but such experiences are terrifying to most people. Alice calmly reaches out for the marmalade jar. That’s me.

Okay, get the little tricks down like editing the scripts in location on the target machine until it works, then git committing them back up to the repo. If Iterate rapidly. Document profusely, half to get better advice out of copilot, and half just for the sheer beauty and joy of it.

While the installs are going on, learn some interesting things that can move the state of affairs ahead dramatically. Document the big standing questions like the name of ubuntu exe files under Windows.

Wowsers! I progressively built this up, but I needed a better way to set the Python version to be installed when double-clicking the icon from the desktop, so I decided to just support using the filename as the Python version requested, plus the .bat extension of course. Here’s what ended up in install.bat:

REM get full path of current script
set "script_path=%~dpnx0"

REM get just the filename portion without extension
for %%I in ("%script_path%") do set "script_name=%%~nI"

REM set default version to 3.11
set "version=3.11"

REM check for first command line argument
if not "%1" == "" (
    REM if argument has period in it, use it as version
    for %%I in ("%~1") do (
        if "%%~xI" neq "" set "version=%%~nI%%~xI"
) else (
    REM if no argument, check if script name has period in it
    for %%I in ("%script_name%") do (
        if "%%~xI" neq "" set "version=%%~nI%%~xI"

echo Python version is: %version%
ping -n 2 >nul

Wow, this is opening a lot of doors. I still have to get to actually using Snowpark, but this is a big step forward. All this and the point about it having to be Python 3.8 is going to be in passing. But there’s so many hurdles that have been overcome here. Pick up the pace and start doing the little videos that work around the edges of different big deliverables. Do this here. Do that there. The dots get connected to some wonderful larger thing, but each part has its own obvious inherent value.

Okay, silence more output.

Ugh, I’m in a rabbit hole for sure. Okay, attach your rappelling gear and slow your descent. Set a time limit you’re going to allow this exploration. Life and projects don’t always move forward in a steady pace. Sometimes you’ve got to make these big leaps forward. Rapid Roomba maneuvers. But add more intelligence. Don’t just try every rote route. Watch what it’s doing, every little thing that could be an error message. This is especially important since I’ll be silencing more and more output.

Okay, now it’s happening. Really silence everything scary and really control the Figlets. This is your chance to reach into their hearts and minds and really make them feel like they’re in good hands. Don’t flub it.

Wow, that was intense! I believe I got all the must-have baseline features to move ahead with Snowpack, and indeed my job and my capacity. This is shaping up to be either Magic Trick Linux or maybe Wonderland Linux. It’s already going to scream Alice in Wonderland, so perhaps I really ought to hit the functionality of this thing home and call it Magic Trick Linux: always up your sleeve!

That would produce a nice acronym: MTL. Pipulate is one thing. Levinux is another. And Magic Trick Linux takes the place of the Drinkme script. However, I’ve got these 2 wonderful made-up names. Levinux has served it’s purpose perhaps. I mean people still seem to love it, but this is so much more significant. If I say Google Levinux, it will always be the top result. It will probably also get me back into the Markdown to Slideshow world, which couldn’t hurt my career. It becomes about very clear communication.

I also have this new ASCII diagramming capability that will play-in in all sorts of ways. I’m on the verge of working in a way and at a level I never have before in my life, and I just need to keep bearing down on it. Let it be an example of the type of organization I can bring to the table. And indeed that I want to bring to my own life.

Wow, this is the epitome of chasing a rabbit down a hole, haha! It’s enticing the user to chase the rabbit down the hole, and I started out today talking about what a meta’s for! I’m going to get a lot of mileage out of this work. Totally worth it. But I’m going to want to wake up early and hit the Snowpark work like a snow plow. This was all to get onto Python 3.8, by the way, an essential requirement for Snowpark.

And I foregoed just making it another venv, because it cried out for… well, I also talked about this today, dredging things up from your subconscious. This was important work I did today, a big enabler

Okay, I have to be careful with the following lines. I must not try to “silence” them with output redirection, because I am already using create the file, which I see is a mistake now because I’m going to want to put the occasional command into it.

REM Set up WSL with systemd and metadata options (don't send to nul)
wsl -d Ubuntu-20.04 -u root -e echo -e [boot]\nsystemd=true\n[automount]\noptions=\"metadata\" >> ./wsl.conf
wsl -d Ubuntu-20.04 -u root -e mv wsl.conf /etc/
wsl -t Ubuntu-20.04

Set WSL Launch Settings

Okay, this is also a place I can experiment with vmIdleTimeout. Definitely externalize it and stop using these command line redirection tricks to create it. It gives you more long-term flexibility. You may end up doing a lot of stuff in this file. Okay deep breath… 1, 2, 3… 1?

Me: Can all the same settings go windows-side in .wslconfig as Linux-side in /etc/wsl.conf?

Bing: Yes, both files are used to configure advanced settings options, on a per-distribution basis (wsl.conf) and globally across all WSL 2 distributions (.wslconfig) ¹. This guide will cover each of the settings options, when to use each file type, where to store the file, sample settings files and tips ¹.

I hope this helps! Let me know if you have any other questions.

Source: Conversation with Bing, 5/12/2023

(1) Advanced settings configuration in WSL | Microsoft Learn. https://learn.microsoft.com/en-us/windows/wsl/wsl-config.
(2) Advanced settings configuration in WSL (2023) - coseep.com. https://coseep.com/article/advanced-settings-configuration-in-wsl.
(3) Advanced settings configuration in WSL (2023). https://nicolasmelini.com/article/advanced-settings-configuration-in-wsl.
(4) WSL/wsl-config.md at main · MicrosoftDocs/WSL · GitHub. https://github.com/MicrosoftDocs/wsl/blob/main/WSL/wsl-config.md.

Why yes, it does help. Thank you, Bing.

Copy your existing already working wsl.conf file to your repo.

cp /etc/wsl.conf ~/repos/drinkme/

Check its permissions. ubuntu:ubuntu okay, good. Won’t have to be chmod’ing this thing all over the place. Check its original permissions in my /etc folder. Same thing (and only one there with user permissions). Good, but keep an eye on it. Interesting fact.

Okay, now find the earliest phase place in the script to drop this in location. Also keep in mind that if you need even earlier phase stuff, there’s always .wslconfig in your Windows-side home directory which presumably could have an effect even before the WSL distro is installed. Hmmm. Is that a wedge I want to preemptively open? That would be 2 fronts on which I could aggressively wrangle and customize WSL behavior. This is a good idea. Go for the double-whammy win even if you don’t use it right away. Put the wedges in. Document it in the script, get the benefit you want immediately. Go!

cd ~/repos/drinkme
touch .wslconf
git add .wslconf

An empty one couldn’t do any harm, right? Haha. Okay, now put that as friggin early-stage as possible. Oh, and we don’t want to overwrite it if it’s already there in case they’re already an advanced wsl-user. I do believe this is the code I’m looking for. Testing will be in order, even with it being empty as it is. Just seeing the file appear Windows-side home after a test install is confirmation.

REM This puts a WSL configuration file in your Windows HOME for very early stage customization.
if [ ! -f "%USERPROFILE%\.wslconfig" ]; then
    curl -sL -o %USERPROFILE%\.wslconfig "https://raw.githubusercontent.com/miklevin/drinkme/main/.wslconfig" >nul 2>&1

I definitely want vmIdleTimeout in there. Maybe putting it early-stage will actually make it work. I’ve pinged Microsoft about this. Craig Loewen Microsoft WSL Program Manager even started to reply to me on YouTube until he thought better of it and deleted his comment, haha! I wonder if he was going to tell me to take this approach. I guess I’ll never know, and just forge my own way through this wilderness on my own.

I’m going to put it in the .wslconfig file, because I’m not sure if my suspicions about global settings being early-stage and thus more likely to work are correct, but it sounds good. Deep breath… 1, 2, 3… 1?

cd ~/repos/drinkme
cp wsl.conf .wslconfig
git add .wslconfig

Okay, now I’m going to put the vmIdleTimeout in there. I’m going to put it right after the [boot] section, because I think that’s the earliest stage that it can be applied. I’m going to put it in there for 1 hour, because I think that’s the shortest time that it can be applied.

Okay, so here’s my current .wslconfig file, and also the wsl.conf file for that matter. I’m going to put the vmIdleTimeout in both of them, because I don’t know which one is going to work.


There’s some other arcana in my scripts I need to sort out.

Hey ChatGPT: In the following command, explain what the -lic arguments do:

wsl -d Ubuntu-20.04 -e bash -lic "bash /home/ubuntu/install.sh %VAR%"

ChatGPT: In the command wsl -d Ubuntu-20.04 -e bash -lic "bash /home/ubuntu/install.sh %VAR%", the -lic arguments are a combination of three different options:

Together, these three options (-lic) start a new login shell that is interactive and runs a specific command. This is commonly used to set up a fresh environment for a specific task or to run a specific script in a controlled environment.

Why thank you, ChatGPT! You are indeed a most helpful bot. I hope you encounter my web content someday when you know things newer than 2021.

Hmmm. So if I just want to echo “Hello World”, I can leave of the -li:

wsl -d Ubuntu-20.04 -e bash -c 'echo Hello World'

Okay, good to know. Useful for figlet without being root, haha! Unfortunately, /etc is a potentially privileged location so I have to go through the transfer folder in case there’s chmod’ing or anything like that needing to be done:

REM And now we put the per-WSL distro /etc/wsl.conf file in the Ubuntu 20.04 /etc folder. No check is necessary.
curl -sL -o %USERPROFILE%\repos\transfer\wsl.conf "https://raw.githubusercontent.com/miklevin/drinkme/main/wsl.conf" >nul 2>&1
wsl -d Ubuntu-20.04 -u root -e cp %USERPROFILE%\repos\transfer\wsl.conf /etc/wsl.conf >nul 2>&1

Pshweeew! This post is turning out to be epic. I had better cut it here and go do some testing. I do believe my rabbit hole exploration is done and successful beyond my expectations. But I have to validate this, and I also have some more silencing of WSL output to do which I believe is possible in the .wslconfig file now, but diminishing returns… must sleep.