Going Native: Using the Windows Subsystem For Linux

Dance with who brung ya

The more and more I play with SQL Server on Linux, or using containers (and orchestration tools like Kubernetes), the more I have come to realize how much I enjoy the Unix/Linux shell environment. And the more I come to enjoy bash (or any native *nix user shell), the more I realize: the shell experiences in Windows… kind of stink.

Listen, before you take up pitchforks folks, let me be clear: scripting languages in Windows are pretty great, PowerShell especially. But as a shell experience, it’s kind of lacking. If you spend a lot of time in Visual Studio code authoring scripts, and then having those scripts run (interactively or otherwise), it’s totally fine. Acceptable, even.

The problem is that if you want to break out of Windows as a shell, there isn’t much to go on. It wasn’t until fairly recently that Windows gained a native SSH shell with the (optional) inclusion of an OpenSSH server pacakge. And while it does add native SSH (and a few other utilities) to your installation of Windows 10, that’s all you get: a ssh.exe you can call from your command line.

And maybe that’s good enough, but usually it isn’t: that’s why we almost always rely on third party applications like PuTTY or MobaXTerm to handle our connections to any remote system that requires SSH. These applications have connection managers that can make managing frequently used connections a little easier, and also give you the ability to import/export keys, but are they any good?

The snob in me says: no, not really. Using other operating systems like Mac OS X or any desktop/server Linux experience provides a much better and native shell to work in. Wouldn’t it be great if there was a much better and on-par shell experience you could use in Windows that would give you a native bash shell to play with? Well, then I’ve got good news for you, and that’s the fact that you can do better.

Speaking my language

Microsoft has provided a native Linux experience for Windows, called the Windows Subsystem for Linux, or WSL. If you haven’t heard of this feature yet, here’s the short version of what this means:

  • “Install” a Linux distribution of you choice into your Windows 10 environment, which
  • Enables you to run common Linux command line tools, like grep and sed, which is something your Linux using friends and co-workers have been bragging about since like, forever, and
  • Gives you access to other Linux applications and commands, available via your chosen distribution’s package manager, and oh before I forget
  • Gives you an honest-to-goodness native SSH shell experience on your machine without the need for a third party application

Sounds cool, right? Well, it is. And getting started is pretty easy, too. Let’s walk through setup. I should mention that this technology is only available on the later(ish) builds of Windows 10, so upgrade already.

To get started, crack open a PowerShell command window (as Administrator) and run the following command:

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

This will enable the Windows feature that lets you install your distribution of choice, and you shouldn’t need a reboot (but hey, you never know). Once it’s done, it’s time to choose which Linux distribution you want to use as a base. Go ahead and knock the dust off of your Microsoft Store icon, and search for, say Ubuntu. Here’s what I get when I do it on my machine:

You’ll notice you get a few choices. Each version of Ubuntu varies (there were some big changes between 16.04 and 18.04, and if you’re not sure what to pick, I’d say stick with 16.04). Click the one you want and click “get.” This will download all the bits you need.

We’re almost done now, but we need to “initialize” the environment with a one-time setup, which includes creating your local user and password. This is a non-root user, but you can still sudo your way to the top with it. Just make sure you remember the username and password you create.

Once this setup is complete, you’re ready to rock and roll.

The best of Linux, on Windows

Why is this so much better than a third-party shell experience? Let’s take a a quick spin of some of the cooler features

Native SSH

Yup, that’s right: you don’t need a to rely on PuTTY anymore. Once you’re running this native subsystem, you get that distro’s version of ssh, along with all the other OpenSSH tools, like scp. And you can manage all your public/private keys separate from what you have set up in Windows, too.

Other cool Linux tools, without the need for a pesky VM

Did you ever want to have commands like curl, sed, tail, and other super common linux commands available to you on your local machine? Well, you do now. These shells come with a host of common Linux commands already installed, and you can use them within your local profile or any file on your Windows installation, as well (see below).

Package management

Oh, and if the tool or command you want isn’t installed be default, your local package manager can probably get it. If you installed Ubuntu, just use apt-get to find what you need. You know, like on an actual Linux installation.

Take, as a for instance, good ol’ trusty nmap. It doesn’t come as part of the install but it’s super useful, so how can we install it? Just like any other Ubuntu package, with apt:

If this doesn’t look like your shell, well, scroll down for a surprise…

Pretty great, right? This goes for just almost any tool you want to install locally, too (and full disclosure, nmap doesn’t work in WSL (yet), I’m just using it as a simple apt example).

Access to your Windows file system

By now, if you’ve got this installed and messed around a little bit, you may be wondering: where’s all my files? That’s because this small shell is using a file system buried deep in your profile’s local AppData folder. And if you start browsing around inside your shell, you might not realize that you can actually break out of your seemingly-isloated sandbox into your Windows file system.

From your shell, if you change your directory over to the /mnt folder, and list the contents…

You can see every drive letter on your PC. Navigating deeper…

TIFU by…

Yup, that’s my C: drive alright. And I can use my native Linux commands there, too. You may hit some strange permission errors when you’re attempting to browse certain directories or open files, but hey, that’s what sudo is for. What could go wrong?

Conclusion: Get comfortable with Linux from the comfort of Windows

If you asked me 5 years ago if I’d be using Linux as part of my daily life, I’d have probably said no. Today though, using Linux is something I do almost every day: I’ve been playing more and more with Linux VMs for development work. I’ve got a local Kubernetes cluster running on a set of six Raspberry Pis. I’ve got a Plex server, again, running on a Linux VM. HASSP? Made possible by SQL Server on Linux. And, let’s not forget: my Mac has a Unix-based heritage, and I use the shell on it just as much as my desktop experience.

The thing is: I want a good shell-based experience. It has to work well, and I don’t just mean “it connects to a server and shows a prompt.” I want as close to a native experience as I can find. The WSL ticks these boxes for me. Not only does it give me a much more friendly, native SSH experience, it tacks on all kinds of other great utilities that any system administrator can love, too.

And this is just the beginning, because WSL2 is on the horizon, which promises even better compatability and new features that sound pretty cool too.

I highly encourage you to give it a shot!

Bonus: beautify your new shell

If you’ve followed along during this tutorial on your own, you might be wondering: “Drew, why does your shell not look like mine? Yours looks like Ubuntu!” Well, that’s because I made it that way. And you can too! I’m going to walk you through how, real quick, because I believe you deserve a pretty shell experience.

First things first, we need to set the font to the Ubuntu Font, which you can grab from here: https://design.ubuntu.com/font/

Once you’ve got it downloaded, drag the fonts over to your font’s folder (or font settings window) to get them installed.

Next, launch your Ubuntu shell. We’re going to set the font manually. Why manually? Well, because until you change something in these settings, there’s no place to automate the rest of our changes. From your newly installed fonts, pick “Ubuntu Mono.”

Now with that out of the way, I’m going to save you a whole bunch of clicking and typing. The PowerShell script below will:

  • Go out to your current user’s registry settings and find the settings for your Ubuntu shell. The problem here is that depending on what version of Ubuntu you installed, and when you installed it, your key name will have a version string attached to it. Which makes this really hard to automate. Fortunately, we can use the settings keys created when we set the font to grab the actual name. That’s what line 2 does with Get-ChildItem.
  • Next, we’re going to take that big chonkin’ registry name and get the actual entry as an object. Line 5 does this.
  • Now that we have this object, we’ll just keep piping it to Set-ItemProperty to set all the colors, highlights, and font sizes and weights to make this look like a base Ubuntu shell.

Here’s the code. Go ahead and drop this into VSCode, save it as a .ps1 file and run it (or run it from VSCode if that’s how you want to roll):

## Get the current installed console values
$consoleName = (get-childitem -path Registry::HKEY_CURRENT_USER\Console | Where-Object {$_.Name -like "*ubuntu*"}).pschildname

##Next, go out and get the current console item from the current user registry
$console = Get-ItemProperty -PATH ("Registry::HKEY_CURRENT_USER\Console\" + $consolename)

$console | Set-ItemProperty -Name "ColorTable00" -Value 432718
$console | Set-ItemProperty -Name "ColorTable01" -Value 10773812
$console | Set-ItemProperty -Name "ColorTable02" -Value 2361904
$console | Set-ItemProperty -Name "ColorTable03" -Value 10131462
$console | Set-ItemProperty -Name "ColorTable04" -Value 204
$console | Set-ItemProperty -Name "ColorTable05" -Value 8081525
$console | Set-ItemProperty -Name "ColorTable06" -Value 41156
$console | Set-ItemProperty -Name "ColorTable07" -Value 13621203
$console | Set-ItemProperty -Name "ColorTable08" -Value 5461845
$console | Set-ItemProperty -Name "ColorTable09" -Value 13606770
$console | Set-ItemProperty -Name "ColorTable10" -Value 3465866
$console | Set-ItemProperty -Name "ColorTable11" -Value 14869044
$console | Set-ItemProperty -Name "ColorTable12" -Value 2697711
$console | Set-ItemProperty -Name "ColorTable13" -Value 11042733
$console | Set-ItemProperty -Name "ColorTable14" -Value 5237244
$console | Set-ItemProperty -Name "ColorTable15" -Value 16772846

$console | Set-ItemProperty -Name "ScreenColors" -Value 47
$console | Set-ItemProperty -Name "PopupColors" -Value 47

$console | Set-ItemProperty -Name "FontWeight" -Value 700
$console | Set-ItemProperty -Name "FontSize" -Value 1310720

The script is pretty straight-forward: it’ll scan you local user keys for the Ubuntu shell, grab the properties, and add a bunch of settings in for the colors and font size and weight. The next time, you run your Ubuntu shell, it should look like this, with colors for everything including directories:

Happy bashing!

UPDATE: If the default Ubuntu look isn’t to your liking, my buddy Mike Fal has created a solarized dark (and light!) script too, which you can find here.

4 thoughts on “Going Native: Using the Windows Subsystem For Linux

    1. Drew Furgiuele

      Thanks Mike, I’ve gone ahead and updated the post to include a link to this. Great stuff!

  1. Pingback: Configuring the Windows Subsystem for Linux – Curated SQL

  2. Jon Kruger

    I’m so excited about this. I really dislike OS X but I do love that it’s built on Linux, especially since most of the dev work I’m doing now is Linux based. Now I feel I can have the best of both worlds. I hope it lives up to the hype.

Comments are closed.