windows10子系统

概述

windows10子系统(Windows Subsystem for Linux,简称WSL)是windows10的一个新特性,相较于cygwin,WSL是内核实现,而cygwin是在用户态实现,wsl效率会更高。wsl2使用类似虚拟机的形式,同时支持GUI程序。

配置启用子系统

  1. 开始菜单-设置-更新和安全-开发者选项-开发人员模式
    此操作会激活开发者模式,并安全相关的软件包
  2. 开始菜单-设置-应用-程序和功能(右侧最下面)-启用或关闭Windows功能-适用于Linux的Windows子系统(勾选)
    确定后,重启电脑,系统更新配置
  3. 切换wsl版本为wsl2
  4. 打开Windows应用市场,输入Linux挑一个自己喜欢的Linux发行版,根据个人偏好选择(debian系还算熟悉,所以安装了debian)
  5. 开始菜单启动WSL(debian),初次启动会有一个短暂的初始化过程,然受输入一个WSL用户名就可以使用了。

基本配置

  1. 为了保证后续操作的顺利进行,先更新下本地软件包缓存
sudo apt-get update
  1. 修复umask问题
vim ~/.profile
if [[ "$(umask)" == '000' ]]; then
    umask 022
fi

常用操作

ssh连接

使用子系统主要就是ssh连接了,相对于debian来说,操作如下

  1. 安装openssh-client
sudo apt-get install openssh-client
  1. 修改ssh-agent
    直接使用ssh-add命令添加公钥失败,需要使用ssh-agent
vim ~/.bashrc
# ssh-agent configuration
if [ -z "$(pgrep ssh-agent)" ]; then
    rm -rf /tmp/ssh-*
    eval $(ssh-agent -s) > /dev/null
else
    export SSH_AGENT_PID=$(pgrep ssh-agent)
    export SSH_AUTH_SOCK=$(find /tmp/ssh-* -name agent.*)
fi

修改WSL默认用户

  1. 打开cmd
  2. 输入以下内容
debian config --default-user <username>

debian 为WSL名称
username 改为需要设置的用户名,如果用户名不存在会自动创建

Windows内执行WSL命令

  1. Win+r打开运行命令对话框
  2. 输入命令
bash -c "command"

参考链接
WSL1 无法运行GUI程序,且剪贴板共享存在问题,WSL2可以解决

运行GUI程序

由于WSL在每次启动的时候IP都无法固定,所以需要为主机和WSL分配新的IP地址;此外,windows10 需要一个X server程序才可以显示WSL2的GUI程序。

@ echo off
%1 %2
ver|find "5.">nul&&goto :Admin
mshta vbscript:createobject("shell.application").shellexecute("%~s0","goto :Admin","","runas",1)(window.close)&goto :eof
:Admin

setlocal enabledelayedexpansion

wsl -u root sudo /myinit/mountNFS.sh
if !errorlevel! equ 0 (
    echo wsl start completed
    :: set wsl2 ip
    wsl -u root ip addr | findstr "192.168.50.2" > nul
    if !errorlevel! equ 0 (
        echo wsl ip has set
    ) else (
        wsl -u root ip addr add 192.168.50.2/28 broadcast 192.168.50.15 dev eth0 label eth0:1
        echo set wsl ip success: 192.168.50.2
    )

    :: set windows ip
    ipconfig | findstr "192.168.50.1" > nul
    if !errorlevel! equ 0 (
        echo windows ip has set
    ) else (
        netsh interface ip add address "vEthernet (WSL)" 192.168.50.1 255.255.255.240
        echo set windows ip success: 192.168.50.1
    )

    tasklist | find /I "vcxsrv.exe"  > nul 2> nul
    if errorlevel 1 (
        echo start vcxsrv
        C:\"Program Files"\VcXsrv\xlaunch.exe -run D:\config.xlaunch
    ) else (
        echo vcxsrv is running
    )
    echo run nvim-qt
    wsl -u root DISPLAY=192.168.50.1:0 nvim-qt --no-ext-tabline --geometry 800x610
)
pause
  1. 脚本开头的mount nfs脚本是自定义脚本,同时也是在WSL2没有启动的情况下,启动WSL2。
  2. 由于分配IP功能需要管理员权限,所以在脚本开头需要提权。
  3. 脚本会判断x server是否运行,如果没有就启动x server。
  4. 为了跳过配置,可以在xlaunch.exe启动时候,保存配置文件,下次启动时候使用
xlaunch.exe -run /path/of/config

参考链接
5. 由于wsl的IP每次开机都会改变,所以只能通过脚本固定ip。在WSL2的.bashrc中设置DISPLAY变量:

export DISPLAY=WSL_IP:0

目前有点存疑,在bat脚本中,执行自定义挂载脚本,bat脚本执行结束后,挂载仍然有效
但是打开新的WSL2窗口,挂载却无效,感觉这个挂载有点像session

windows 在安装wsl以后,执行bash命令将自动进入wsl环境,注意区分

常见问题

WSL参考的对象不支持尝试的操作

WSL2在使用vpn后可能会无法启动,解决方案:
管理员权限运行cmd

netsh winsock reset

WSL访问Windows文件,没有权限

WSL默认会再/mnt/下面挂在Windows的各个分区
可以通过mount参数查看挂载参数,drvfs是windows10最近新增加的挂在模式,能有效避免WSL内文件权限污染问题.
gid,uid决定挂载后的文件归属信息,umask,fmask决定文件的默认权限

umount /mnt/c
mount -t drvfs C: /mnt/c/ -o metadata,uid=1000,gid=1000,umask=022,fmask=111

持久化修改

  1. 修改配置文件
vim /etc/wsl.conf
[automount]
enabled = true
root = /mnt/
options = "metadata,uid=1000,gid=1000,dmask=022,fmask=133"
mountFsTab = false
  1. 重启lxssManager服务

参考链接:https://blogs.msdn.microsoft.com/commandline/2018/01/12/chmod-chown-wsl-improvements/

值得注意的是:外部Windows的权限设置大于WSL内的权限设置,所以如果外部文件没有访问权限,即便WSL内有权限也无法访问

Error: 0x800703fa - Press any key to continue

启动Ubuntu的时候报错如下:

Error: 0x800703fa - Press any key to continue

解决办法只要打开服务管理,重启LxssManager服务解决
我的服务管理器里显示LxssManager为手动模式,且无法改成自动(非管理员账户,权限不够),可以使用管理员cmd解决

  1. 开始菜单-cmd-(右键-以管理员身份启动)
  2. 执行以下命令
sc config LxssManager start=auto

每个子系统通常都有一个子系统服务进程和一个内核态驱动,对于Windows子系统,分别是著名的CSRSS.exe和Win32K.sys.对于WSL,以系统服务形式运行的子系统服务进程LxssManager.LXSSManager服务支持运行本机ELF二进制文件.该服务提供在Windows上运行ELF二进制文件所需的基础结构

相关链接

WSL安装指南
WSL2运行图像应用
debian镜像源

总结

整体来说,WSL就是一个完整的系统,并不像cygwin那样只是命令环境的模仿,所以能更接近真实linux环境.