WSL tricks
This post shares some WSL (Windows Subsystem for Linux) tricks. The Windows Subsystem for Linux lets developers run a GNU/Linux environment – including most command-line tools, utilities, and applications – directly on Windows, unmodified, without the overhead of a virtual machine.
Tip: If you haven’t heard of WSL, you can find more information here.
When I installed WSL Ubuntu, and setup the development environment using my dotfiles, I encountered some issues and inconveniences, such as:
- New directory is created wrongly with 777 permission.
- Directory shows ugly green background.
- Need to input passphrase for my private key every time I ssh into a machine.
- Cannot open directory from WSL.
- …
Below I list solutions for each of those issues.
Wrong 777 permission
Basically, there are two kinds of 777 permission issues. They are:
- The mounted directories from Windows system (like files in C drive) having 777 permission.
- Newly created directories on WSL having 777 permission.
For mounted directories from Windows system
On WSL, add below contents to /etc/wsl.conf
, if that file doesn’t exist,
create a new one. You may need to restart WSL or Windows system in order to make
the settings alive.
[automount]
options = "metadata,umask=022"
Tip: For more information about WSL settings, please visit here
For newly created directories
When you create a new file in an interactive shell, the file permission is given
according to mask value. You can check that value by running umask
in your
shell. If the value is 0000
, then it means the newly created directory will be
given 777 permission (rwxrwxrwx).
There are two solutions for this issue.
The first solution is adding below contents to your ~/.bashrc
or ~/.zshrc
.
umask 002
The second solution is to ask wsl.exe
to launch a login shell through
/bin/login
. Run below command in cmd.exe
or powershell.exe
or your
favorite terminal, change the username to your own:
wsl.exe -u root -- /bin/login -f username
Note: The side-effect is that specific paths will be removed from PATH environment variable.
Windows executables PATHs are missing
If you use the second solution from here, or for some reason, you find some Windows executables PATHs are missing from WSL shell’s PATH environment variable. You can use below way to append Windows paths to PATH environment variable, so that you can call your favorite Windows executables from WSL.
Add below contents to your ~/.bashrc
or ~/.zshrc
:
if [[ "$(uname -r)" =~ Microsoft$ ]]; then
_path="$(/mnt/c/Windows/System32/cmd.exe /c "echo %PATH%" | tr ";" "\n" | sed -Ee 's/^([C-Z]):/\/mnt\/\l\1/' -e 's/\\/\//g' | tr "\n" ":")"
if [[ -n "$_path" ]]; then
PATH="$PATH:$_path"
fi
fi
Start ssh-agent automatically
If your private key is protected by a non-empty passphrase, you may need to
input the passphrase every time you push to github or ssh into a machine. To
avoid this, you can start ssh-agent once you open a terminal or start a new
interactive shell. Add below contents to your ~/.bashrc
or ~/.zshrc
:
# Share a same ssh-agent across sessions.
if [ -f ~/.ssh-agent.generated.env ]; then
. ~/.ssh-agent.generated.env >/dev/null
# If the $SSH_AGENT_PID is occupied by other process, we need to manually
# remove ~/.ssh-agent.generated.env.
if ! kill -0 $SSH_AGENT_PID &>/dev/null; then
# Stale ssh-agent env file found. Spawn a new ssh-agent.
eval `ssh-agent | tee ~/.ssh-agent.generated.env`
ssh-add
fi
else
eval `ssh-agent | tee ~/.ssh-agent.generated.env`
ssh-add
fi
Access Windows clipboard in nvim on WSL
According to this wiki, we can use
win32yank to access windows clipbard
in nvim, but the steps are too many, and win32yank.exe
must be put outside of
WSL rootfs in order to work. I only want to do a quick setup on WSL side. Here
comes the dragon.
We can use clip.exe
that comes with Windows system to copy something to
clipbard. To get from clipbard, Windows doesn’t provide such utility. We can use
powershell.exe -command Get-Clipboard
to do that. But that costs too much time
to run on WSL. So we need a more efficient way to implement that.
Here is a package that provides two
commands pbcopy.exe
and pbpaste.exe
, which are much like OSX’s
pbcopy/pbpaste. Install it through scoop.
scoop install https://raw.githubusercontent.com/uzxmx/scoop-extras/master/bucket/pasteboard.json
After the installation, make sure scoop shims are in $PATH. Run type
pbpaste.exe
to check if it’s in $PATH. You may need to restart the terminal if
$PATH doesn’t contain scoop shims.
Add below contents to your ~/.vimrc
:
if system('uname -r') =~ 'Microsoft'
let g:clipboard = {
\ 'name': 'WSLClipboard',
\ 'copy': {
\ '+': 'clip.exe',
\ '*': 'clip.exe',
\ },
\ 'paste': {
\ '+': 'pbpaste.exe --lf',
\ '*': 'pbpaste.exe --lf',
\ },
\ 'cache_enabled': 1
\ }
endif
Tip: For more information about g:clipboard
in nvim, run :h g:clipboard
.
Reopen nvim. This time, when you press y
to yank, the text should go to
clipboard, and when pressing p
to paste, the content of clipboard should be
pasted.
Open directory or URL from WSL
If you have used much CLI in OSX system, you must be familiar with open
command. It can open a file or directory in Finder window, also can open a web
page if the parameter is with HTTP schema. So how to do these on WSL? Here’re
some examples that show how to do that.
cmd.exe /c "start explorer.exe C:\\Windows"
cmd.exe /c "start explorer.exe C:\\Users"
cmd.exe /c start "http://example.com"
Note: The directory passed to explorer.exe
must be Windows path (not WSL
path like /mnt/c/Windows). To open a browser, the parameter must be with
http://
or https://
prefix.
For a full convenient script, you can reference the bash script open which imitates OSX’s open.
Remove ugly green background for directories
A color init string consists of one or more numeric codes, seperated by ;
. For
example:
OTHER_WRITABLE 34;42
EXEC 00;31
Below are all numeric codes:
Attribute codes:
00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed
Text color codes:
30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
Background color codes:
40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white
For OTHER_WRITABLE 34;42
, it means o+w directory has blue text and green
background. For EXEC 00;31
, it means executable file has red text, with no
attribute and no background.
In order to update the color, we first generate default colors by executing:
dircolors -p >~/.dircolors
Then open ~/.dircolors
, change the color of the target type. For example,
change color of OTHER_WRITABLE
from 34;42
to 00;34
, the background will
be removed.
After changing any color, add below content to your ~/.bashrc
or ~/.zshrc
:
eval "$(dircolors ~/.dircolors)"
For Zsh user, you also need to add below content to make the color normal when auto-completing.
zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
Then start a new shell. You shouldn’t see ugly green background any more.
Use vagrant
Vagrant supports
WSL, but some of Vagrantfile and plugins may not support it. For example, if you
use ubuntu/bionic64
box, in ~/.vagrant.d/boxes/ubuntu-VAGRANTSLASH-bionic64/0/virtualbox
there is a line shown below:
vb.customize [ "modifyvm", :id, "--uartmode1", "file", File.join(Dir.pwd, "ubuntu-bionic-18.04-cloudimg-console.log") ]
The above line will stop vagrant working on WSL. Because it sets a WSL path in
Virtualbox, but Virtualbox cannot find that path, we must convert the WSL path
to Windows path so that it can work. There is also a quick workaround
here. For such reason, I
suggest not to use vagrant on WSL. Instead, use vagrant on Windows directly.
Because I use centos/7
as my base box, unlike ubuntu/bionic64
it works well
on WSL, so I still insist on using vagrant on WSL.
When using vagrant on WSL or Windows, the vagrant project should exist outside of WSL rootfs so that virtualbox or vagrant can find the correct path.
Kernel panic - not syncing
If you run Vagrant Centos/7 box, you may experience an error Kernel panic - not syncing on Virtualbox 6.0.8. A workaround is to use Virtualbox 6.0.6. I haven’t tried if it works in the latest version.
Agent forwarding issue
This issue only appears when using vagrant on Windows (not WSL). When we run vagrant, it cannot find ssh agent inside WSL, so ssh agent forwarding may not work. As a workaround, we can use ssh directly.
# This one will not work.
vagrant ssh -- -A
# This one will work. Replace the port with the correct port which will be
# shown when you run `vagrant up` or `vagrant ssh-config`. Below line
# assumes the current working directory is vagrant project root directory,
# you may need to ensure the private_key file has correct permission.
ssh vagrant@localhost -p port -i .vagrant/machines/default/virtualbox/private_key -A