关于WSL的参考文章很多,在此辑录少许,也将自己遇到的坑稍加编撰。

参考

WSL安装过程

美化及开发环境配置

设置WSL的默认浏览器为Windows下的Chrome

安装过程

上手两星期有余,更新到Windows 18272之后突然不能开启了,先把WSL复制然后重置了,到WSL的github issue发现这个版本有问题,于是回滚到上个版本。但是系统怎么也恢复不了。无奈,只能再安装一次,顺便写个详细点的日志。

1. 安装准备

  • 申请Inside 预览计划

需要开启开发者模式,不然那可能会出问题,接受不到更新

查看当前系统版本

1
cat /etc/issue

如下等待写作:

2. 更换软件源并更新软件

Ubuntu 的软件源配置文件是 /etc/apt/sources.list,我们将其更换为国内软件源,来加快更新的下载速度。打开 清华大学开源软件镜像站,选择自己的Ubuntu版本,得到该文件内容。先备份系统原文件,再创建新文件,即可使用 TUNA 的软件源镜像。Ubuntu命令行输入:

1
2
3
4
sudo mv /etc/apt/sources.list /etc/apt/sources.list.bak
sudo touch /etc/apt/sources.list
sudo vi /etc/apt/sources.list
# 然后将镜像内容粘贴进来保存

执行下面代码,更新所需软件,这需要一定时间。如果发现没有联网,可以重启电脑再试:

1
2
3
# 更新软件到最新
sudo apt-get update && sudo apt-get --assume-yes upgrade
sudo apt autoremove

3. 更好用的Terminal

Windows自带的终端实在惨不忍睹,作为替代,可以使用 wsl-terminal,简单几步就能有体验原生般的体验。

  • 快速打开wsl-terminal并进入HOME目录:

    新建 wsl-terminal-home-path.bat 文件:

1
path\to\your\open-wsl.exe -l

​ 建立该文件的快捷方式,更改名称,自定义图标,并将快捷方式放到C:\ProgramData\Microsoft\Windows\Start Menu\Programs\ 下面,即可通过Win键快速打开,真香!

  • 在当前位置通过右键menu启动 WSL

    运行wsl-terminal目录下 ./tools/1-add-open-wsl-terminal-here-menu.js 就完成了

  • wsl-terminal更多实用技法

    更多用法可以参考其官网说明,或者这位知友的专栏文章

  • wsl-terminal 使用 zsh 遇到的坑

    如果简单的使用 chsh -s /bin/zsh 命令会尴尬的发现 wsl-terminal 启动后还是bash,而wsl原生的shell进入的话就直接是zsh了,这显然是开倒车,令人无法接受。经过折腾发现:执行上面代码后需要将wsl-terminal根目录下 ./etc/wsl-terminal.conf 里的 shell=/bin/bash 改成 shell=/bin/zsh 就好了。

    之前所需的环境信息可以放在~/.zshenv 文件里就好了。

  • terminal 的其他选择

4. 桌面环境和X-server

笔者尝试过安装Gnome,以失败告终,此处可以选择轻量级的桌面xfce4,安装所需时间较长:

1
2
3
# 为了xorg,安装下xfce4
sudo apt-get install --assume-yes xfce4
sudo apt-get install --assume-yes xorg-dev

因为 WSL 只能是命令行形式的,所以我们需要使用 X-server ,让 Ubuntu 里运行的GUI 程序有窗口显示。可以使用 VcXsrv Windows X Server,并以这样的配置打开:

img

输入以下命令:

1
2
3
4
5
6
# 安装必要组件
sudo apt install libgtk2.0-0 libxss1 libasound2
# 配置显示参数
echo 'export DISPLAY=:0.0' >> .profile
# 测试是否安装成功
sudo apt install x11-apps -y && xeyes

如果出现了跟随鼠标转动的小眼睛,那么 XServer 就安装成功了,能够显示Ubuntu里的GUI程序。

X-server的其他选择

5. 中文输入和显示

在WSL中,Windows文件已经mount在/mnt/下面,我们将Windows的字体文件全部导入到WSL的字体中:

1
2
3
4
# 将windows的字体放入ubuntu里,并更新缓存
sudo mkdir /usr/share/fonts/windows
sudo cp -r /mnt/c/Windows/Fonts/*.ttf /usr/share/fonts/windows/
fc-cache

安装中文输入法

  • 安装谷歌拼音:
1
2
# 安装输入法及所需的包,这里选择谷歌输入法
sudo apt-get --assume-yes install fcitx fcitx-googlepinyin dbus-x11
  • 设置zh_CN.UTF-8
1
sudo locale-gen zh_CN.UTF-8
  • 设置环境变量,将下面代码添加到~/.profile文件里,然后重启下shell。
1
2
3
4
5
# 设置中文 & 输入法
export LC_ALL="zh_CN.UTF-8"
export XMODIFIERS=@im=fcitx
export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
  • 中文输入法设置
1
2
3
# 如果运行时长时间卡住,按回车
fcitx
fcitx-configtool
  • 运行输入法的 GUI 设置工具,通过 + - 调整候选输入法,可选项要至少包含:English(US)和 Google Pinyin。为了不与Windows的快捷键冲突,这里将输入法切换快捷键改成了Ctrl + `

由于每次开机后启动WSL,默认不会启动dbus 和 fcitx服务,需要设置

  • 设置开机启动 dbus 和 fcitx 服务,可以将下面代码添加到~/.bashrc
1
2
3
if [ $(ps -ax | grep dbus-daemon | wc -l) -eq 1 ]; then
  eval `dbus-launch fcitx > /dev/null 2>&1`
fi

如果仍出现无法输入中文的情况,则在shell内手动输入以下代码:

1
2
3
# 如果用的是 zsh,则将 bash 改成 zsh
dbus-run-session -- bash
fcitx

6. 管理 wsl 的相关命令

在 cmd / PowerShell 中运行 wsl , bash, Linux系统名称(如 ubuntu),即可进入 Linux 系统。

以下命令都是在cmd / powershell 下运行来管理子系统:

1
2
3
4
5
6
7
8
// 设置默认运行的linux系统
wslconfig /setdefault <DistributionName>
// 卸载linux系统
wslconfig /unregister <DistributionName>
// 查看已安装的linux系统
wslconfig /list
// 设置默认登陆用户
ubuntu config --default-user root

如果WSL损坏,可以把子系统删了重来

1
2
 // 删除 Ubuntu 子系统
wslconfig /unregister Ubuntu

开发环境配置

1. zsh 与 oh-my-zsh

想要快乐地使用命令行,一个趁手的 Shell 是必不可少的。

  • 下载安装 zsh 代替自动补全功能欠缺的 bash

    利用 Ubuntu 的包管理器安装 zshsudo apt install zsh

    修改 .bashrc 加入以下代码,使得默认 shell 变成 zsh

    1
    2
    3
    
    if [ -t 1 ]; then
      exec zsh
    fi
    

    加载设置:source ~/.bashrc

  • 下载安装 oh-my-zsh,一个好用的 zsh 配置管理工具:

    运行命令下载安装:sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" (提醒没有什么就安装什么。)

  • 去除 lscd 命令之后背景色出现的问题:

    修改 .zshrc,添加如下代码

1
2
3
4
5
6
7
# Change ls colours
LS_COLORS="ow=01;36;40" && export LS_COLORS

# make cd use the ls colours
zstyle ':completion:*' list-colors "${(@s.:.)LS_COLORS}"
autoload -Uz compinit
compinit

加载设置:source ~/.zshrc

基本的终端环境就到这里了。

2. Python开发环境

选择 MiniConda 还是 Anaconda ? conda 是包管理工具,miniconda 发行版在此基础上捆绑了少量的包,anaconda 发行版则捆绑了足量的包,此处可以按照个人需求选择。

  • 安装 Miniconda,一路 Enter ,最后一步选 yes
1
2
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh
  • 换国内镜像源?

(2019.05.28 更新)目前国内大多数Anaconda镜像源已经挂掉,如果您之前使用的第三方镜像停止服务,请换回官方镜像。更多帮助信息,可参考 https://zhuanlan.zhihu.com/p/64766956 此外,上海交通大学镜像源的Anaconda镜像对校内IP开放:https://mirrors.sjtug.sjtu.edu.cn/#/

  • (可选)如需更改默认环境的Python版本,使用conda install python=3.6

  • 接下来更新包:

1
2
conda update conda
conda update --all
  • 安装常用包
1
conda install jupyter notebook pandas matplotlib numpy scipy

设置 pip 源

  • 修改 ~/.pip/pip.conf ,没有就先创建文件夹及文件:
1
2
mkdir ~/.pip
vim ~/.pip/pip.conf
  • 加入如下内容:
1
2
3
4
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
[install]
trusted-host=mirrors.aliyun.com

3. Jupyter 相关

Jupyter notebook / JupyterLab启动相关

安装体验 JupyterLab : conda install -c conda-forge jupyterlab 或者 pip install jupyterlab

使用X-server打开WSL内置的FireFox浏览器,交互上可能不太便捷,个别X-server可能会出现按键连续响应的情况,可以用如下方法在Windows 下的浏览器中打开。先让jupyter运行在无浏览器模式:

1
2
jupyter notebook --no-browser
jupyter lab --no-browser

然后在你的Terminal里点击链接,就是用Windows下的浏览器打开了。(要点击斜杠位置哦 🖱 ,这样才能识别完整的链接)。当然你也可以更改wsl的默认浏览器为Windows下的浏览器,这里就不赘述了。

为了启动方便,可以在~/.bashrc里设置别名:

1
2
alias jnote='jupyter notebook --no-browser'
alias jlab='jupyter lab --no-browser'

链接Windows下的Matlab

此处要注意matlab的版本支持问题,MatlabR2018b版本支持Python 2.7, 3.5, 3.6,如你使用3.7版本,可以通过如下方法魔改:Jupyter Notebook(Python3.7)如何支持MATLAB?

  • 在wsl侧安装matlab_kernel :pip install matlab_kernel
  • 在Windows侧打开matlab安装的如下位置:MATLAB版本号/extern/engines/python,在此处打开wsl-terminal
  • 运行:python setup.py install
  • 在Jupyter下就能看到啦,但是提示 No kernel 无法运行,待解决 😭

OSError: Please reinstall MATLAB Engine for Python or contact MathWorks Technical Support for assistance: No module named ‘matlabengineforpython3_6’

matlab-kernel 0.15.2 matlabengineforpython R2018a

可能是需要魔改一番了。

如何卸载:

1
2
3
4
5
6
7
setup.py 帮助你纪录安装细节方便你卸载
python setup.py install --record log
这时所有的安装细节都写到 log 里了
想要卸载的时候
cat log | xargs rm -rf
就可以干净卸载了
vi dist/matlab/engine/__init__.py

然而 pip 安装包的名字是matlabengineforpython3-6,根本不可能

matlabengineforpython

想法是错的,原dist在windows可以跑,应该是架构的问题

  1. 调用windows下的python
  2. 找出importlib的工作机理

凉凉呀

调试了两天,发现是自己解决不了的问题,matlabengineforpython3-6.pyd文件是.dll,对于linux下的.so文件,怎么能让import调用呢,没时间考虑了。

4. Github添加SSH key, git

https://help.github.com/articles/connecting-to-github-with-ssh/

1
2
3
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
ssh-add ~/.ssh/id_rsa
clip < ~/.ssh/id_rsa.pub

github https://github.com/settings/ssh/new

1
2
git config --global user.email "you@example.com"
git config --global user.name "Your Name"

5. 其他环境

  • Installing Node

如果你使用zsh,请替换为.zshrc

Node is almost as easy to install, let’s use nvm for that inevitable day where we have to support mutliple versions of Node.

1
2
3
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.9/install.sh | bash
source ~/.bashrc
nvm install --lts

You should now have node and npm installed.

  • Installing Ruby and Rails

Ruby has a few more dependencies. Thankfully WSL has improved so that we can follow any generic “How to Install Ruby on Rails” tutorial, I like this one from Digital Ocean.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
sudo apt install autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm3 libgdbm-dev
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
source ~/.bashrc
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
rbenv install 2.5.1 --verbose
rbenv global 2.5.1
echo "gem: --no-document" > ~/.gemrc
gem install bundler
gem install rails

You don’t technically need --verbose for installing Ruby via rbenv, but having some progress indicator helps with your sense of time.

深入讨论

1. 安装多个发行版

Windows 10 Fall Creators Update 之后,WSL 支持同时安装多个 Linux 发行版,直接在 Microsoft Store 中搜索想要的发行版并点击安装即可。这些发行版可以同时运行,并且数据互相独立。你可以使用 wslconfig.exe 来查询已安装的发行版,或者更改默认的发行版。

3. 多种进入 WSL 的方式比较

新版支持同时安装多个发行版,那自然不能像以前那样只提供一个 bash.exe 入口了。

秋季创意者更新之后的 Windows 提供了 多种进入 WSL 环境的方式

  • wsl.exe

    打开默认发行版中的默认 Shell。

  • <distroname>.exe

    打开指定发行版中的默认 Shell。

  • bash.exe (DEPRECATED)

    打开默认发行版中的 bash Shell。

    如果你更改了默认 Shell 却总是打开 bash,就说明你使用了这个入口。

你也可以通过这些入口直接在 WSL 中执行命令并返回结果:

  • <distroname> -c [command]
  • bash -c [command]
  • wsl [command](不再需要指定 -c

4. 与 Windows 的互操作性

WSL 与 Windows 之间的互操作性 (Interoperability) 很牛逼。怎么个牛逼法呢?

Windows 下的所有盘符都挂载在 WSL 中的 /mnt 目录下,可以直接操作。WSL 中的所有数据则存放于 C:\Users\{你的用户名}\AppData\Local\Packages\{Linux发行版包名}\LocalState\rootfs 目录中(不要在 Windows 中修改这些文件,这会造成文件权限错误):

1
2
3
4
5
6
7
$ ls /mnt
c  d  e
$ mount -l
rootfs on / type lxfs (rw,noatime)
C: on /mnt/c type drvfs (rw,noatime,uid=1000,gid=1000)
D: on /mnt/d type drvfs (rw,noatime,uid=1000,gid=1000)
E: on /mnt/e type drvfs (rw,noatime,uid=1000,gid=1000)

你可以在 Windows 命令行环境中直接调用 WSL 中的命令:

1
2
3
4
5
PS C:\temp> wsl ls -al
total 0
drwxrwxrwx 1 printempw printempw 4096 Sep  7 19:04 .
drwxrwxrwx 1 printempw printempw 4096 Sep  7 18:38 ..
-rwxrwxrwx 1 printempw printempw    4 Sep  7 19:04 foo.txt

你也可以在 WSL 中调用 Windows 中的命令行程序:

1
2
3
4
5
$ which ipconfig.exe
/mnt/c/Windows/System32/ipconfig.exe
$ ipconfig.exe
Windows IP Configuration
...

你可以在 WSL 中直接启动 Windows 应用:

1
$ notepad.exe "C:\temp\foo.txt"

你还可以通过 pipes 与 Windows 程序通信:

1
2
# 复制内容至 Windows 剪贴板
$ cat foo.txt | clip.exe

你甚至可以把 Windows 命令和 WSL 命令混着用:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
PS> ipconfig | wsl grep IPv4
IPv4 Address. . . . . . . . . . . : 192.168.1.114

$ ipconfig.exe | grep IPv4 | cut -d: -f2
192.168.1.114

$ ls -al | findstr.exe foo.txt
-rwxrwxrwx 1 printempw printempw    4 Sep  7 19:04 foo.txt

$ cmd.exe /c dir
 Volume in drive C is Windows
 Volume Serial Number is B263-****

 Directory of C:\temp

2018/09/07  19:04    <DIR>          .
2018/09/07  19:04    <DIR>          ..
2018/09/07  19:04                 4 foo.txt
               1 File(s)              4 bytes
               2 Dir(s)  194,422,341,632 bytes free

同时,WSL 与 Windows 共享网络栈,也就是说你可以:

  • 在 WSL 中启动 web server,在 Windows 上使用浏览器访问;
  • 在 Windows 下启动 MySQL/Redis 服务器,在 WSL 中连接;
  • 诸如此类。

如果你对 WSL 与 Windows 之间互操作的原理有兴趣,可以参考一下这些文章:

5. DrvFs 文件权限问题

虽然 WSL 中可以直接访问 Windows 磁盘的内容,但如果你曾经这么做过,你应该对这样绿油油一片的 ls 不会感到陌生。为什么 NTFS 文件系统中的文件到 WSL 下权限就全部成 0777 了呢?

ls-with-wrong-file-permission

这主要是 DrvFs 中 Linux 文件权限的实现导致的。

在 WSL 中,Microsoft 实现了两种文件系统,用于支持不同的使用场景:

  • VolFs

    着力于在 Windows 文件系统上提供完整的 Linux 文件系统特性,通过各种手段实现了对 Inodes、Directory entries、File objects、File descriptors、Special file types 的支持。比如为了支持 Windows 上没有的 Inodes,VolFs 会把文件权限等信息保存在文件的 NTFS Extended Attributes 中。记得我上面警告过你不要在 Windows 中修改 WSL 里的文件吗?就是因为 Windows 中新建的文件缺少这个扩展参数,VolFs 无法正确获取该文件的 metadata,而且有些 Windows 上的编辑器会在保存时抹掉这些附加参数。

    WSL 中的 / 使用的就是 VolFs 文件系统。

  • DrvFs

    着力于提供与 Windows 文件系统的互操作性。与 VolFs 不同,为了提供最大的互操作性,DrvFs 不会在文件的 NTFS Extended Attributes 中储存附加信息,而是从 Windows 的文件权限(Access Control Lists,就是你右键文件 > 属性 > 安全选项卡中的那些权限配置)推断出该文件对应的的 Linux 文件权限。

    所有 Windows 盘符挂载至 WSL 下的 /mnt 时都是使用的 DrvFs 文件系统。

由于 DrvFs 的文件权限继承机制很微妙,最后导致的结果就是所有文件的权限都变成了 0777。而且由于早期的 DrvFs 不支持 metadata,所以你无法给这些文件 chown/chmod,只能对着绿油油的 ls 干瞪眼。不过好消息是,Windows Insider Build 17063 之后,DrvFs 也像 VolFs 一样支持给文件写入 metadata 了

要启用 DrvFs 的 metadata 支持,你需要添加参数重新挂载磁盘:

1
2
3
# 修改成你自己的盘符
$ sudo umount /mnt/e
$ sudo mount -t drvfs E: /mnt/e -o metadata

不过如果仅仅是执行了这个,虽然支持了文件权限的修改,但磁盘下的文件权限默认依然还是 0777,除非你给它们整个 chmod 一遍。如果你不想这么做,也可以指定其他的 mount 参数:

1
$ sudo mount -t drvfs E: /mnt/e -o metadata,uid=1000,gid=1000,umask=22,fmask=111

这样磁盘下的文件的默认权限就是 0644ls 也不会再是绿油油一片啦。

ls-with-fixed-file-permission

不过每次使用时都要重新挂载未免也太烦,我们可以通过另一个新特性 Automatically Configuring WSL实现自动挂载。在 WSL 中创建 /etc/wsl.conf,在其中填写如下内容:

1
2
3
4
5
6
7
[automount]
enabled = true
root = /mnt/
options = "metadata,umask=22,fmask=111"
mountFsTab = true

# 这个文件里还可以添加其他配置项,有兴趣的可以看看上面的链接

重启终端,所有的盘符就会使用上面的配置自动挂载啦(可以使用 mount -l 查看)。

另外,如果你想要给不同的盘符设定不同的挂载参数(上面的方法对所有盘符都有效,如果你想在 WSL 中运行 Windows 下的应用程序,就得每次都 chmod +x 一下,所以我一般都会把 C: 排除掉),就需要手动修改 /etc/fstab。首先确保 wsl.conf 中的 mountFsTabtrue,然后编辑 /etc/fstab,添加如下内容:

1
2
3
# 不在此列表中的盘符会使用 wsl.conf 中的参数挂载
# 格式可以自己去查 fstab 的帮助文档
E: /mnt/e drvfs rw,relatime,uid=1000,gid=1000,metadata,umask=22,fmask=111 0 0

6 其他关于 WSL 的折腾

虽然 Microsoft 开发 WSL 出来主要是着重于命令行环境的使用,但经过测试,WSL 是可以通过 X Server 执行 GUI 应用程序的,甚至还可以在 WSL 里面用 Wine 执行 Windows 程序……(🤔?)

也有人试过在 WSL 中运行完整的 DE,体验似乎还不错,有兴趣的同学可以去试试。

另外,你也可以通过某些神秘的方法用上 Microsoft Store 未提供的 Linux 发行版,比如 Arch Linux

如果你对 WSL 的底层实现有兴趣,也可以去围观一下 WSL 的官方博客:

踩坑

在此列举我遇到的一些问题,大部分还没解决。大家遇到问题时可以先到wsl的github issue 搜索。

  • Ubuntu18.04 配置Gnome桌面环境失败
  • wsl 中 chrome 无法运行
  • jupyter notebook 与 selenium 无法同时使用chrome
  • jekyll 没问题
  • 如何备份系统
  • WSL与Windows的时差

使用该命令显示错误:

1
timedatectl set-local-rtc 1 --adjust-system-clock

换用如下命令,把时区调整到Asia / Shanghai就好

1
sudo dpkg-reconfigure tzdata