
Hands-on test of Windows Subsystem for Linux
Undercover
The new Linux subsystem [1] has been around since the Windows 10 Creators Update; according to Microsoft, it can get by without a resource-consuming virtual machine (VM) and configuration. It is also said to offer a more native Linux feeling than the previous Cygwin [2] Linux environment. Linux users have used Cygwin on Windows for years, for example, to automate processes with shell scripts (e.g., mass Git checkouts), but it does mean recompiling Linux programs for Windows.
A look at the subsystem is worthwhile because of the surprisingly lightweight, process-based virtualization concept that just might catch on. In this article, I explain the limitations of the subsystem compared with native Linux and Cygwin, and I offer a number of customization tips that help make the subsystem fit for everyday use.
Installation
Users of Windows 10 Professional, at least, will be able to pick up the Linux subsystem easily. The subsystem runs natively on Windows and does not require an additional VM. If you do not want to create a Microsoft account during the install, you can install Ubuntu 16.04 LTS directly by using Windows PowerShell. As an administrator, the command
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
prepares Windows for installing the subsystem (Figure 1, top). Next, select Settings | Update & Security | For developers
to enable Developer mode
(Figure 2). Once the installation is complete, type bash
to display the prompt (Figure 1, bottom). Like all applications under Windows, the bash shell shown in Figure 3 is launched from the Start menu by calling bash.exe
.



Home Is Home
After double clicking on bash.exe
, you will find yourself in a Linux shell with an Ubuntu environment. Even the Apt package manager is there waiting for you. Windows saves the subsystem files under C:\Users\<pa>\AppData\Local\lxss
. Conversely, Ubuntu mounts Windows under /mnt/c
.
To save typing and avoid redundant data structures, it is best to merge the Linux and Windows home directories first. For this purpose, change the path to your Linux home directory in the /etc/passwd
file so that it points to your Windows home /mnt/c/users/<pa>
. The Vi editor, which you call by typing sudo vi /etc/passwd
, helps you do this on Windows. After restarting Bash.exe
, you land directly in the Windows home directory.
Startup Problems
Differences from a native Linux system are already apparent with the use of a user-specific C:\Users\<pa>\AppData\Local\lxss
path: In contrast to the normal procedure, the services that Ubuntu usually links in the /etc/init.d
directory do not start up automatically at boot time. They also terminate along with the shell. Although the Apache web server can be configured in the usual way, you have to boot it manually every time. After closing Bash.exe
, it cannot be reached at all.
A command to register a Linux service under Windows (e.g., cygrunsrv
under Cygwin) does not yet exist for the new subsystem. However, you can live with this restriction, because you will always open a shell to start work.
Peculiar Permissions
Other peculiarities await. All files below /mnt/c
belong to root. Changes to user rights with chmod
and chown
are ineffective. This handicap does not seriously disrupt usability, however, because you can freely create and delete files and directories in your subsystem.
However, if you want to transfer user rights for files during a data transfer, it has to be set up during or after the transfer. Rsync offers a solution for this:
rsync --perms --chmod=+wrx,go-w index.html server:/var/www
The perms
parameter makes sure that the synchronization tool also transfers the directory rights. In the first step, chmod
sets all rights for the user, the owner group, and everyone else using +wrx
. In the second step, the go-w
expression deprives the group and others of write permissions. In this way, the transferred file (here, index.html
) receives the rwxr-xr-x
permissions. Incidentally, Rsync uses filters to distinguish between directories (D
) and files (F
). An additional F-x
expression as the third element in the comma-separated list would eliminate the ability of all files to be executed.
If you would prefer to use your own SSH key, the script in Listing 1 backs up the SSH key and config
files from your home directory into the /etc/ssh
folder. If you do without the script, calling the ssh myserver
command throws up the Bad owner or permissions on /mnt/c/users/<pa>/.ssh/config error message.
Listing 1: Adapting SSH
01 #!/bin/bash 02 cd ~ 03 if [ -d .ssh ]; then 04 tar cf ssh.tar .ssh 05 for keyfile in `grep -le 'BEGIN .* PRIVATE KEY' -e '^ssh-' .ssh/*`; do 06 filename=`filename $keyfile` 07 mv $keyfile /etc/ssh 08 chmod 644 /etc/ssh/$filename 09 done 10 if [ -f .ssh/config ]; then 11 cat .ssh/config >> /etc/ssh/ssh_config 12 sed -i 's|~/.ssh|/etc/ssh|g' /etc/ssh/ssh_config 13 rm -f .ssh/config 14 fi 15 fi
At the end, back up Listing 1 as the file ssh-extend.sh
and call it – also in the shell – with the sudo bash ssh-extend.sh
command. In line 2, the script initially switches to the home of the user. If any content exists in the ~/.ssh
folder, line 4 saves it using the tar
archive command. The for
loop iterates over all the files that the grep
expression identifies as key files.
The character strings after the -e
switch work as regular search patterns. Line 7 moves a key file to /etc/ssh
each loop run; line 8 sets appropriate access rights.
Assuming ~/.ssh/config
is available, the script transfers the settings of this configuration file into the global SSH configuration file. In line 11, the script attaches the found entries to the end of the /etc/ssh/ssh_config
file using the >>
operator. The sed
command then uses search and replace to replace the ~/.ssh
path prefix with /etc/ssh
. Because the Linux subsystem is in the Windows users directory, there is no threat of a breach of security from the transfer of key files in the subsystem. SSH can then be used in the shell as usual.
Nuclear Fission
The limitations of the subsystem should be a lot greater for programs that have access to kernel features, because the Linux subsystem has to make do without the Linux kernel. However, Linux processes run in a new process type called Pico [3] in the Windows user space (Figure 4). Windows translates kernel calls from the Pico process through Pico providers Lxss and LxCore into calls to the Windows kernel and forwards them transparently.

You can check how well this works with the Docker container solution. Similar to Cygwin, the Creators Update makes it possible to call .exe
files from the Shell. If you install Docker under Windows and .bashrc
in the home directory and then add the Bash code from Listing 2, the Docker commands can be used after restarting the shell, as in Linux. The for
loop frees all .exe
files from their file extensions and connects them to the Linux world with an alias.
Listing 2: Configuring Docker
DOCKER_BIN='/mnt/c/Program Files/Docker/Docker/resources/bin' for f in "$DOCKER_BIN"/*; do alias "$(basename "$f" | sed 's/.exe$//')" '="'"$f"'"' done
Only the interactive terminal mode (option -t
, as in the docker run -it debian bash
command) fails, because Bash cannot interpret the Windows terminal protocol. Creating an appropriate pseudo-terminal with
sudo /sbin/MAKEDV -v pty
also failed in the test. Under Cygwin, the winpty
command helps achieve the desired result [4].
What a Shame: Paths
Windows and Linux use different path schemes to address resources within their directory tree. With Subversion, for example, you can check a working copy of the repository document with the file:///C/Users/<pa>/svn/documents
Windows path.
However, a subsequent attempt to update the working copy with the svn update
Bash command fails, because Linux cannot cope with the source path.
This class of issues is sometimes fixed with a diversion into the network world, because Linux and Windows analyze URLs in the same way. Under Subversion, the command
sc create svnserve binpath= "\"C:\Program Files\TortoiseSVN\bin\svnserve.exe\" --service -r C:\User\<pa>\svn" displayname= "Subversion Server" depend= Tcpip start= auto
entered with administrative privileges initially registers the internal svnserve
server as a Windows service. The sc start svnserve
command starts the service; then, check out a working copy by URL:
svn checkout svn://localhost/documents
This time, Subversion is working in both worlds.
Be aware that to write data, you need to add the anon-access = write
line to the conf/svnserve.conf
file in the root directory of the C:\User\<pa>\svn
repository.
Domain Sockets
Implementing Domain sockets only seems to working partially according to a blog post [5]. The attempt to create such a socket with
sudo nc -U /var/tmp/sockted
fails with nc: unix connect failed: No such file or directory.
Similar to the path problem, the solution here is to run interprocess communication via TCP/IP, as in the case of the D-Bus system. If you are not afraid of a bit of extra work, you will find another blog post on this topic online [6]. To sum up, you need to install an X server such as vcxrc
or Xming, add the export DISPLAY=:0.0
entry to .bashrc
, and use the command
sudo sed -i 's$.*$tcp:host=localhost,port=0$' /etc/dbus-1/session.conf
to tell D-Bus to communicate via TCP/IP. Then, Firefox launches and – so people claim – the Ubuntu desktop too.
Conclusions
The Windows Subsystem for Linux shows a lightweight, container-based virtualization approach that relies on its own process class. In practice, there is a still scope for improvement, if you want to work with Linux in the usual way or require at least the level of maturity that Cygwin already has. However, a few simple steps help to create a system fit to work and harmonize with the Windows superstructure. It remains to be seen whether Microsoft is willing to complete its subsystem.