Playing with Windows Subsystem for Linux (WSL)
Tags: wsl, windows
Published: 2020-05-14 00:01:43

Windows 10 comes with Windows Subsystem for Linux which provides a seamless experience for running Windows and Linux at the same time. Seamless being the keyword here. Allowing 1) run Windows commands using Linux 2) Run Linux commands through Windows 3) Run HTTP services and access as if everything is accessible through localhost etc. This can be handy if you're a developer and want to work on both Windows and Linux without jumping hoops through VMs.

# Enable WSL
First, you need to enable the WSL. Settings > Turn Windows features on or off > Windows Subsystem for Linux. Click OK and restart.

![Enable WSL Windows feature](https://dev-to-uploads.s3.amazonaws.com/i/mbeapz0tr0cmg9yvw801.png)

# Install a Linux distribution
Next you have to install a Linux distribution from the Windows Store. Let's install Ubuntu.

![Install Ubuntu from Windows Store](https://dev-to-uploads.s3.amazonaws.com/i/ckfl531burs7xna2zwfh.png)

After the installation, click on Launch and it's going to set up the distro and create a user. You will be asked to enter a username and a password. This will be the Linux user account that'll be used to login.

At this point we have a working Linux system. You can install all other Linux packages necessary for development through apt-get.

# Install Windows Terminal (optional)
The new Windows Terminal provides quick access to multiple shells with a tabbed interface. You can install this through Windows Store. Here we're going to install it through [Chocolatey](https://chocolatey.org/) (a popular package manager for Windows).

Start an administrative PowerShell and execute this powershell-fu (taken from https://chocolatey.org/install). Skip this step if you already have Chocolatey.

```powershell
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
```

![Install Chocolatey](https://dev-to-uploads.s3.amazonaws.com/i/2wm1pb1zp47dobs98esl.png)

Type in ```> choco install microsoft-windows-terminal``` to install the new terminal. Reboot.

# Running Windows commands in Linux
After installing Docker Desktop for Windows and enabling Kubernetes, you can run the .exe (any .exe for that matter) directly within Ubuntu. ```> docker.exe run hello-world```

![Running Windows commands in Linux](https://dev-to-uploads.s3.amazonaws.com/i/evyo20reb7mw1x0ze6w3.png)

# Running Linux commands from Windows

Using the wsl command in Windows you can run any Linux command within a Windows command shell / powershell. Such as ```> wsl lsb_release -a```

![Run Linux commands through wsl](https://dev-to-uploads.s3.amazonaws.com/i/w7fx47y2ndlqjqjgrl6g.png)

# Redirect output of a Windows command to a Linux command (piping)

You can also run one command in Windows and pipe the output to a command in Ubuntu which is very nice. ```> Invoke-RestMethod http://www.mocky.io/v2/5ebc6fec3100007e005b0b67 | ConvertTo-Json -Depth 5 | wsl jq```

![Pipe output of one command to another](https://dev-to-uploads.s3.amazonaws.com/i/zuumot2i91j6kahwgu3e.png)

# Using localhost to access services

Another convenience is you can use localhost for accessing services launched from  either Windows, Linux, docker or kubernetes. As you can see below,

## Start service in Windows, access from Linux

Starting up a simple Java service.

![Start Java service in Windows](https://dev-to-uploads.s3.amazonaws.com/i/vf58x13ocpi9zi1049da.png)

Accessing the service from Linux. We're just using localhost and the port 9090 (which my sample service is listening on)

![Accessing the service from Linux](https://dev-to-uploads.s3.amazonaws.com/i/26y8lqmnt13y4ovvrxro.png)

## Start a service in Linux, access it from Windows

Let's create a simple Ruby on Rails project.
```bash
> rails new blog
> cd blog
> rails server
```
![Start rails server](https://dev-to-uploads.s3.amazonaws.com/i/25cokp4nb6qw4fqaqt2a.png)

Access from browser in Windows,

![Access rails app from Windows](https://dev-to-uploads.s3.amazonaws.com/i/4afodh6kcxpygao7npfg.png)

## Deploy an app in Kubernetes

I've installed [Docker Desktop for Windows](https://www.docker.com/products/docker-desktop) (Edge) and have enabled Kubernetes. After that docker.exe and kubectl.exe can be executed from PowerShell as well as within Ubuntu without having to do anything.

Let's use following example app that runs Wordpress with MySQL on K8S to test out - https://github.com/kubernetes/examples/tree/master/mysql-wordpress-pd

![Deploying K8S app](https://dev-to-uploads.s3.amazonaws.com/i/rl0826ecrj81ozodvig0.png)

After we deploy everything the app is available through localhost:80 (look at output of kubectl.exe get services wordpress)

![Access wordpress](https://dev-to-uploads.s3.amazonaws.com/i/klve349rlapnh6ohmg84.png)

# In conclusion

WSL provide a nicer way of working with Linux without having to go through the trouble of installing VirtualBox, then installing a guest Linux OS, setup file share and access the system through an SSH server.

Seamless integration works really well when working with standalone commands, interactively piping from one tool-set to the other, working with simple HTTP services and working with containers on Kubernetes.