WSL is nice on its own, but I’ve found a few ways to make it integrate with Windows a lot nicer! So this is what I do when I set up WSL!
The first thing I do when I set up a new WSL instance is make a few symlinks between the two systems.
The first one is for the root drive (Requires root):
ln -s /mnt/c /host
Then I add a few folders in my home folder that make the link between Windows and Linux pretty seamless. (If you already have these folders, you might need to move or nuke them first)
If you aren’t running this from Emacs, you can hit [Windows] + [R]
, type ”%userprofile%
” and hit [Enter]
. Then hit [Ctrl] + [L]
type ”bash
” and [Enter]
again.
This should put you in correct folder this should be run from.
for i in Desktop Documents Downloads Videos Music Pictures; do
ln -s $i ~
done
mkdir ~/Documents/Code ~/Documents/Writing
ln -s ~/Documents/Code ~/Documents/Writing ~
After installing Chocolatey, installing some essential programs can be done from the following in an elevated command prompt.
choco install xming autohotkey wsltty -y
And after that’s done, the wsltty terminal can be set up with the following:
C:\ProgramData\Chocolatey\lib\wsltty\tools\wslttyinstall\install.bat
My configuration for wsltty is basically just to make it look like a simple and slightly transparent terminal:
This goes in %APPDATA%\wsltty\config
ThemeFile=dainty-monokai-night-mod
Transparency=5
OpaqueWhenFocused=no
CursorType=block
Font=Consolas
FontHeight=11
ZoomShortcuts=no
AltFnShortcuts=no
BackgroundColour=0,0,0
The above theme is follows, and goes in %APPDATA%\wsltty\themes\dainty-monokai-night-mod
(Originally from here, and modified slightly for contrast):
# source: https://github.com/alexanderte/dainty-wsltty
# MIT License
BackgroundColour=40, 40, 40
Black=51, 51, 51
Blue=106, 126, 200
BoldBlack=102, 102, 102
BoldBlue=129, 154, 255
BoldCyan=102, 217, 239
BoldGreen=166, 226, 46
BoldMagenta=195, 159, 255
BoldRed=249, 38, 114
BoldWhite=248, 248, 242
BoldYellow=226, 226, 46
CursorColour=248, 248, 240
Cyan=86, 173, 188
ForegroundColour=222, 222, 222
Green=134, 180, 43
Magenta=195, 159, 255
Red=196, 38, 94
White=227, 227, 221
Yellow=179, 180, 43
For XMing, I update my .Xresources file to get a slightly nicer looking X11:
Xft.antialias: 1
Xft.dpi: 96
Xft.hinting: 1
Xft.hintstyle: hintsfull
Xft.lcdfilter: lcddefault
Xft.rgba: rgb
Then I edit my ~/.profile to include things like the following at the end:
# Allow graphical Linux programs to know how to connect to XMing
export DISPLAY=127.0.0.1:0
# Make XMing look nicer
xrdb -merge $HOME/.Xresources
For AutoHotKey, I make a little script to start wsltty when I hit Ctrl + Alt + T
, just like the default keybinding in a lot of Linux window managers.
^!t::
Run, C:\Users\Archenoth\AppData\Local\wsltty\bin\mintty.exe --WSL= --configdir="%APPDATA%\wsltty" -~
Return
I also make a little vbscript file to run XMing, and then to start bash once (to run my .profile with the Linux-side XMing configuration):
CreateObject("Wscript.Shell").Run """C:\Program Files (x86)\Xming\Xming.exe"" :0 -clipboard -multiwindow", 0, False
CreateObject("Wscript.Shell").Run "bash -lic exit", 0, True
After making these, I copy shortcuts for that last two scripts above into my shell:startup
folder. (You can access by typing that into the run dialog you get by hitting Win + R
)
That will make this stuff all start on login, and without popping up any ugly command windows on startup. (That’s why I used vbscript here–to squelch the command prompt popups)
To get Linux services starting on Windows start (Before anyone logs in), I create a startup script in etc named after the user that will run it, so in my case, I call it rc.arch.local
:
#!/bin/bash
service cron start
service ssh start
I then add my user to a sudoers files to allow this to be run as root without a password:
# Startup script access for default user
archenoth ALL=(root) NOPASSWD: /etc/rc.arch.local
In Windows, I open up the Task Scheduler and make scheduled tasks to run the /etc/rc.arch.local file with passwordless sudo when the computer starts.
This is what the task I made looks like exported as XML (You may need to change the user in here if you are planning on importing it into your Task Scheduler):
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Date>2019-11-08T12:49:06.8481246</Date>
<Author>JIRACHI\Archenoth</Author>
<Description>Starts the Linux Subsystem rc.arch.local script</Description>
<URI>\WSL rc.arch.local</URI>
</RegistrationInfo>
<Triggers>
<BootTrigger>
<Enabled>true</Enabled>
</BootTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>S-1-5-21-3695860422-1816032588-548272057-1001</UserId>
<LogonType>S4U</LogonType>
<RunLevel>LeastPrivilege</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>true</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>true</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT72H</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>C:\Windows\System32\bash.exe</Command>
<Arguments>-c "sudo /etc/rc.arch.local"</Arguments>
</Exec>
</Actions>
</Task>
I didn’t bother with vbscript for this one since it runs before I even log on, so there still aren’t any command prompt popups.
And that about covers the main tweaks I make! Feel free to steal as many of these ideas as you like..! ^^
These aren’t as major, but they are nice little things I sometimes enjoy being able to use.
I wrote a little Windows binary that, if you rename it to a Linux command, that Linux command will run. So if you like having git.exe on your path, you can use the Linux version with your Linux SSH config.
To set it up, you can run the following:
mkdir -p /host/Oshawott/bin
wget https://github.com/Archenoth/wsl_proxy/releases/download/0.2.0/wsl_proxy.exe -O /host/Oshawott/wsl_proxy.exe
remaining=1023
find /bin /usr/bin /usr/local/bin /usr/sbin -executable -type f -maxdepth 1 ! -name bash -printf "%f\n" \
| sort | uniq | while read bin; do
echo "Linking $bin"
if [ "$remaining" -le "0" ]; then
remaining=1023
cp /host/Oshawott/wsl_proxy.exe /host/Oshawott/wsl_proxy2.exe
mv /host/Oshawott/wsl_proxy.exe "/host/Oshawott/bin/$bin.exe"
mv /host/Oshawott/wsl_proxy2.exe /host/Oshawott/wsl_proxy.exe
else
remaining=$((remaining-1))
ln /host/Oshawott/wsl_proxy.exe "/host/Oshawott/bin/$bin.exe"
fi
done
This will download the wsl_proxy.exe
program, and link every executable in a number of bin folders likely on your $PATH
. (We aren’t gonna use $PATH
proper since it will return many executables that aren’t actually if you have any Windows paths in there)
The 1023 links per copy business is because each file can have only a maximum of 1024 links at any given time. (And yes, WSL hardlinks work on Windows)
To use this, you’ll need to change your “Path” in sysdm.cpl
under “Advanced” -> “Environment Variables” -> “User variables for <you>” to include C:\Oshawott\bin
.
You can use command_not_found_handle
to automatically append .exe
to your commands if they don’t exist on Linux and try again.
All you need to do is modify the handle in bash.bashrc to look like:
if [ -x /usr/lib/command-not-found -o -x /usr/share/command-not-found/command-not-found ]; then
function command_not_found_handle {
if which "$1.exe" 1>/dev/null 2>&1; then
EXE="$1.exe"
shift
$EXE $*
return $?
else
# check because c-n-f could've been removed in the meantime
if [ -x /usr/lib/command-not-found ]; then
/usr/lib/command-not-found -- "$1"
return $?
elif [ -x /usr/share/command-not-found/command-not-found ]; then
/usr/share/command-not-found/command-not-found -- "$1"
return $?
else
printf "%s: command not found\n" "$1" >&2
return 127
fi
fi
}
fi
Since WSL does pathname translation, this means you can do crazy things like explorer Code/ahk
and it will open that code folder with explorer.exe
properly if it’s in your $PATH!
Note: Programs run this way won’t work on paths that only WSL can see. Which is another good reason to have symlinks between your two systems set up!
I don’t really like how tab completion, or many other actions in Linux make my computer ding at me, so I like to replace the bell-style
in /etc/inputrc to be set bell-style none
.
I mostly wrote this file for myself, but if you stumbled across it somehow, I hope you found these tricks useful!