阅读 8244

在Windows上舒适地使用Linux子系统(一):WSL的安装及配置

WSL介绍

使用适用于 Windows 的 Linux 子系统,开发人员可运行 GNU/Linux 环境 (包括大多数命令行工具、实用程序和应用程序),直接在 Windows 上进行修改,而不会造成虚拟机的系统开销。

你可以:

  1. 选择你最喜爱的 GNU/Linux 发行版。
  2. 运行常见命令行的自由软件,如grepsedawk,或其他 ELF 64 二进制文件。
  3. 运行 Bash shell 脚本和 GNU/Linux 命令行应用程序,这包括:
    • 工具: vimemacstmux
    • 语言:Javascript/node.jsRubyPythonC /C++C# & F#RustGo 等。
    • 服务:sshdMySQLApachelighttpd
  4. 使用自己的 GNU/Linux 发行版包管理器安装其他软件。
  5. 使用类似于 Unix 的命令行 shell 调用 Windows 应用程序。
  6. 在 Windows 上调用 GNU/Linux 应用程序。

WSL安装

Microsoft Docs官方安装方式

微软官方提供了2种安装方式:Microsoft Store商店安装以及下载.appx安装包自行安装,不过这2种方式都不能自定义安装位置,官方的wsl.exe功能也比较少,不方便管理wsl子系统。不过这里还是贴上链接:

适用于 Linux 的 Windows 子系统文档

使用第三方开源软件LxRunOffline

这是一款非常强大的wsl管理软件,具有 自定义安装wsl卸载已安装的wsl查看已安装的wsl转移已安装的wsl系统的位置备份/导出wsl设置wsl默认登录用户 等实用功能。具体的安装&使用方法可以参考下面这篇文章,讲的非常详细:

使用 LxRunOffline 优雅的管理 WSL:转移目录、备份、设置默认用户

使用Windows-Terminal来启动终端

使用官方方式安装wsl有一个优点:安装完成后,会有一个专门用于wsl子系统的Terminal终端,如下图所示:

官方的wsl终端

然而使用LxRunOffline安装后,似乎只能使用Windows祖传的cmd,通过输入wsl或者bash来启动wsl,有点令人不爽。

好在微软在2019年发布了一款全新的终端应用程序:Windows Terminal,它同时适用于cmd命令提示符powershellwsl等其他shell命令交互的用户。

安装

打开微软应用商店,搜索Windows Terminal安装即可。(需要更新win10的版本到最新的1903

设置默认shell

默认情况下,打开Windows Terminal时,会使用powershell,虽然可以通过新增一个标签页来使用wsl,但有强迫症的我还是有些不爽,那么,如何设置默认的shellwsl呢,其实很简单,方法如下:

  1. 打开Windows Terminal,查看本系统上已经安装的shell种类,找到你之前安装的wsl,记住它的名字,然后打开Settings设置,如图:

    设置默认shell(一)

  2. profiles.json中,找到wsl对应的配置区域中的guid字段,然后将defaultProfile字段的值改为此guid的值,如图:

    设置默认shell(二)

  3. 保存并退出,重启Windows Terminal

添加到右键菜单

如果要实现如下的效果:

右键打开windows terminal

需要执行的操作如下:

  1. 下载Windows Terminal的图标,然后存放到一个地方:terminal.ico

  2. 新增一个.txt文本文本文档,输入如下内容:

    Windows Registry Editor Version 5.00
    
    [HKEY_CLASSES_ROOT\Directory\Background\shell\wt]
    @="Windows Terminal here"
    "Icon"="你刚才下载的图标的存储路径\\terminal.ico"
    
    [HKEY_CLASSES_ROOT\Directory\Background\shell\wt\command]
    @="C:\\Users\\你自己的用户名\\AppData\\Local\\Microsoft\\WindowsApps\\wt.exe"
    复制代码
  3. 保存,然后修改后缀名为.reg,然后双击运行。

  4. 打开Windows Terminal,点击Settings,在对应shell的配置区域中新增一个字段 "startingDirectory": null,保存,然后就可以了。如图:

    右键打开windows terminal(二)

如果要从右键菜单移除的话,只需要打开注册表,找到 HKEY_CLASSES_ROOT\Directory\Background\shell\wt 然后把整个 wt 删除即可。

其他设置

其他有关windows terminal的自定义改造,比如更改字体、主题、透明度、光标等等样式之类的,可参考下面这些github上的官方文档:

Windows Terminal用户文档

使用JSON来进行用户自定义设置

Profiles.json配置文档

互操作性

文件访问

WSL 的一个优点是, 可以直接访问Windows文件系统中的文件。

WSL 将计算机的固定驱动器挂载到 Linux的 /mnt/<drive>文件夹下。比如,你的C:盘驱动器挂载在/mnt/c/下。

不要在Windows下直接访问WSL Linux文件系统中的文件,一个比较好的做法是:在Windows文件系统下单独创建一个文件夹,这个文件夹下存放着Windows和WSL都需要访问的文件,然后不管哪一方对文件做了变动,另一方都可以实时共享。

从Windows命令行运行Linux工具

使用wsl.exe <command>从 Windows 命令提示符 (CMD 或 PowerShell) 运行 Linux 二进制文件或命令。例如:

windows命令行执行WSL Linux工具

从WSL运行Windows工具

WSL 可以使用[binary name].exe从 WSL 命令行直接调用 Windows 二进制文件。 例如, notepad.exe 。 为了使 windows 可执行文件更易于运行, windows 路径包含在$PATH秋季创意者更新中。例如:

从WSL执行Windows程序

更换国内软件源

我的是Ubuntu 18.04系统的wsl,使用的是清华软件源,更换方法如下:

  1. 复制以下内容:(如果你的wsl是其他系统,可前往清华大学开源镜像站选择相对应的源镜像地址)

    # 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
    deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse
    # deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse
    deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse
    # deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse
    deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse
    # deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse
    deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse
    # deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse
    复制代码
  2. wsl中执行以下命令:

    sudo vim /etc/apt/sources.list
    
    ### 进入vim普通模式
    
    	输入 ggdG 清空文件内容
    	然后输入 i 进入编辑模式
    	直接点击 鼠标右键 将之前复制的内容粘贴进来
    	然后按 ESC 键退出编辑模式
    	输入 :wq 来退出vim
    	
    ### 退出vim,回到shell
    
    sudo apt update && sudo apt upgrade
    复制代码

配置中文环境

设置系统语言-区域(locale)为中文-中国

执行locale -a命令查看已安装的locale,如图:

设置locale(一)

如果没有安装zh_CN的话,执行locale-gen zh_CN.utf8命令来安装。

安装完成后,执行update-locale LANG=zh_CN.UTF-8命令来将系统locale切换到中文-中国环境。

可以执行locale命令来查看当前系统的locale配置信息,如图:

设置locale(二)

确保切换成功后,重启wsl来使其生效。

安装中文字体

如果没有中文字体的话,后面在通过X-Window运行GUI程序时,中文会全部显示异常。可以直接将Windows下的所有字体拷贝到wsl中,命令如下:

# 将windows的字体放入wsl里,并更新缓存
sudo mkdir /usr/share/fonts/windows
sudo cp -r /mnt/c/Windows/Fonts/*.ttf /usr/share/fonts/windows/
fc-cache
复制代码

为WSL安装SSH-Server

在Windows上安装了wsl子系统后,如果我们想要在另一台电脑上远程访问此wsl,则我们可以通过为wsl安装ssh server来实现。

还有一种情况是在Windows上通过ssh连接到本地的wsl,有人说这不是多此一举吗,既然是在本地那我直接运行wsl不就好了吗,干嘛绕这么一圈。。。事实上我安装wsl的目的就是为了学习Linux,以及在CLion上将wsl作为构建工具链,因为wsl是直接运行在Windows本地嘛,所以我本来以为CLion使用wsl作为构建工具链是采用了一种特殊的方式,结果到配置界面一看,和Remote Host形式的工具链是一样的,都是采用ssh连接,说白了就是把wsl当作远程主机来用。然后CLion的官方使用说明里还提供了一个wsl一键安装open-ssh server并开机自启动ssh服务的脚本,还是比较方便的。好吧,那既然这样的话,就用官方的脚本吧,命令如下:

wget https://raw.githubusercontent.com/JetBrains/clion-wsl/master/ubuntu_setup_env.sh && bash ubuntu_setup_env.sh
复制代码

安装完成后,检查ssh服务是否已处于运行状态以及连接是否没问题:(脚本里设置的端口是2222,也可以自己改)

/etc/init.d/ssh status 
ssh username@localhost -p2222
复制代码

使用X Window让WSL运行GUI图形程序

LinuxX Window图形系统是一个经典的Server/Client架构。在系统中如Firefox等需要显示GUI界面的应用程序,实际上是作为客户端即X Client,这些程序在编写的过程中自然需要调用与界面显示相关的API,但这些API实质上只是一层封装,它真正做的事情是发送大量绘图相关的底层指令。而真正在调用显卡等硬件资源进行窗口绘图等实际操作的,则是另外一个独立的X Server服务端,它可以看作是一个独立的服务器程序。这两者通过正常的网络协议进行通信,服务端接收到客户端的绘图指令之后,在屏幕上绘制图像。

通过上面的介绍,我们可以了解到:在之前的ssh连接中,wsl是作为server来被连接,而在X Windows中则恰恰相反,wsl是作为client来向X Server发送绘图请求。

下面是以本机Windows作为X ServerWSL作为X Client的配置方法。当然,X Server不一定非得是本机Windows,也可以是远程机器,配置方法是一样的,只需要改一些参数就可以了。

WSL配置X Client

Linux系统中,环境变量DISPLAY用来指示这些绘图指令被发送到的地址和端口,它的值的格式如下:

hostname:D.S
复制代码
  • hostname:表示X Server所在主机的域名或者IP地址,比如说本机Windows,那它的值就是localhost或者127.0.0.1。如果省略,那就表示本机localhost
  • D:它可以理解为X Client的一个编号,因为对于每一个X连接,X Server端都会分配一个监听端口来对应着每一个X Client,映射关系是:listen port = 6000 + <D>。如果只有一个X Client,那就是0;如果有多个X Client连接到一个X Server,那么每个X Client的编号值就是依次递增。
  • S:屏幕编号。一台机器可能连接了多个屏幕,每个屏幕从0开始编号加以区分,这个参数用来指示图形应该显示在X Server主机的哪个屏幕上,默认就是0。

可以将export $DISPLAY = value环境变量加入~/.bashrc里,避免每次打开wsl都要重新添加,以本机Windows作为X Server的示例配置如下:

sudo vim ~/.bashrc

### 进入VIM
### 在末尾加入
export DISPLAY=localhost:0.0
### 退出VIM

source ~/.bashrc
复制代码

本机Windows配置X Server

Windows下X Server的实现软件有很多,这里选择了VcXsrv,原因是比较新,更新也比较频繁。安装配置方法如下:

  1. 下载并安装VcXsrv
  2. 打开XLaunch进行配置,过程如下:

配置VcXsrv

在我的电脑上,如果不关闭 [native opengl] 选项,在wsl中打开GUI软件时会报错。

  1. 以后如果要运行X Server,直接在桌面打开config.xlaunch就可以了。X Server是在后台运行的,如果要关闭,在任务栏找到其小图标,右键关闭即可。

测试配置是否成功

随便在wsl中运行一个GUI图形程序即可,比如:

使用XWindow在wsl中运行GUI程序

其他一些问题

如何终止正在运行的WSL

Windows开机后,当我们第一次打开wsl.exeWindows Terminal或者是在cmd输入bash等等其他的方式,wsl子系统就会启动。但是,当我们将终端窗口关闭时,它只是将这个终端窗口程序以及bash shell关闭了而已,wsl还是在后台运行着,不信你可以用ssh连接试试看。而且你在wsl中输入shutdown -h now会提示System has not been booted with systemd as init system (PID 1). Can't operate.,因为wsl中不支持systemd,所以这个方法也行不通。

通过查询官方文档得知,关闭wsl还是得使用wsl.exe程序,在Windows的命令行中输入:

wsl --terminate <DistributionName>

即可终止指定的wsl系统。可以考虑写一个简单的powershell脚本,如果不想每次都打开命令行输入的话,如下:(本来想写复杂点的,但是脚本中获取命令结果总是乱码,加上powershell语法我感觉学起来很蛋疼,就随便写了个粗暴的)

$wsl_running = wsl --list --running
if($wsl_running.count -lt 5)
{
    Read-Host "没有正在运行的WSL,按任意键继续..."
}
else
{
    wsl --terminate ubuntu-wsl
    Read-Host "已成功终止ubuntu-wsl,按任意键继续..."
}
复制代码

WSL中运行vim,光标切换相关的问题

这个问题可谓是头疼了我好久,因为我发现在wsl中运行vim,光标不会在不同的模式下切换,一直跟shell中保持一样的形状,不好区分。然后在.vimrc中将普通模式的光标改为方格形状后,退出vim回到shell模式光标又没有变回来,在google上搜了好久,折腾了好几天,最终总算解决了。下面给出配置方法:

  1. 首先给出不同光标形状对应的数字编号:

    1 2 3 4 5 6
    闪烁块 █ 块 █ 闪烁下划线 ▁ 下划线 ▁ 闪烁竖线 ┃ 竖线 ┃
  2. 更改shell命令交互模式时的光标形状,这个应该是在每个终端的设置里面改的,不同的终端可能不一样,windows Terminal的更改光标形状可参考其他设置

  3. 确定你在不同模式下想要的光标形状,就拿我自己来说,我的习惯是:shell命令交互下光标形状是5vim普通模式下是1,插入模式下是5,替换模式下是3。确定了需求之后,就可以进行配置了。

  4. 打开~/.vimrc文件进行vim配置,参考如下:

    " 进入插入模式下的光标形状
    let &t_SI.="\e[5 q"
    
    " 进入替换模式下的光标形状
    let &t_SR.="\e[3 q"
    
    " 从插入模式或替换模式下退出,进入普通模式后的光标形状
    let &t_EI.="\e[1 q"
    
    " 进入vim时,设置普通模式下的光标形状
    autocmd VimEnter * silent !echo -ne "\e[1 q"
    
    " 离开vim后,恢复shell模式下的光标形状
    autocmd VimLeave * silent !echo -ne "\e[5 q"
    复制代码
  5. 最后的效果:

    WSL vim光标配置

Windows Terminal无法输入中文

这个终端目前还处于Preview状态,所以bug缺陷什么的还是有点多,最大的一个问题就是不管是在Windows Terminal上运行cmdpowershell还是wsl等其他shell,都无法切换为微软拼音来输入中文,这个bugWindows Terminal的官方的github仓库上已经开了一个issue,感兴趣的可以去关注一下进展:CJK IME doesn't work #2213

如果你实在是要在wsl中经常输入中文,可以换一个其他的终端,比如wsl-terminal,有官方中文教程,使用起来也还不错,链接:wsl-terminal安装方法