Windows 10 上 WSL 的安装和使用笔记

Windows Subsystem for Linux,简称 WSL,是在 Windows 里运行的 linux 子系统,是除了虚拟机以外,在 Windows 10 机器上运行 linux 的又一选择,目前最好的 Linux 桌面发行版。体验还不错,可以替代 Linux 虚拟机的大部分作用。

安装

  1. 在 windows 10 控制面板的“程序和功能”中,“启用或关闭 windows 功能”处,勾选“适用于 Linux 的 Windows 子系统”,确认、重启。
    wsl install step one
  2. 在Microsoft Store 中,搜索并安装 linux 发行版,如 https://www.microsoft.com/store/productId/9N9TNGVNDL3Q 。首次运行需要较长时间初始化,不要提前关闭窗口,否则安装不完整,就需要卸载重装了。我是 windows 10 version 1803 上安装的 ubuntu 18.04。

ssh 登陆

实践发现并不需要改端口,22 端口就可以。ssh 服务需要手动启动sudo service ssh start (自动启动见下文),默认的 ssh 有点问题,需要生成一下key:

sudo ssh-keygen -A
sudo service ssh --full-restart

可以编辑配置:sudo vi /etc/ssh/sshd_config, 将 PasswordAuthentication 改为 yes,允许用户名+密码登陆。
ssh key 可以与Windows 系统使用同一个,也可以使用 ssh-keygen 命令生成新的,我是直接从 Windows 系统的用户目录下复制过来:

mkdir .ssh
chmod 700 ~/.ssh
cp /somewherefromwindows/.ssh/id_rsa ~/.ssh/
cp /somewherefromwindows/.ssh/id_rsa.pub ~/.ssh/
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
cp ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys

如果碰到问题,可以卸载掉默认的 openssh 重新安装:

sudo apt purge openssh-server
sudo apt install openssh-server

常用软件

Nginx+PHP+MySQL

nginx 直接使用包安装即可:

sudo apt install nginx
sudo service nginx start

注意我在使用 nginx.org 上的源进行包安装时,无论 stable 版本还是 mainline 版本,错误日志里都出现了
io_setup() failed (38: Function not implemented),换成 ubuntu 默认仓库安装就没问题:

➜  ~ nginx -v
nginx version: nginx/1.14.0 (Ubuntu)
➜  ~ 

PHP 我使用了 ppa 安装:

sudo add-apt-repository ppa:ondrej/php
sudo apt-get update
sudo apt-get install unzip curl php-fpm php-mysql php-mbstring php-xml php-json php-curl php-redis php-intl php-zip php-gd php-sqlite3 php-bcmath
sudo service php7.2-fpm start

安装后配置 nginx + php-fpm 时,发现页面一直加载不停,搜索了一圈后我找到了解决办法,在 nginx 配置的 http 部分加一条设置:

http {
        ...
        fastcgi_buffering off;
        ...

MySQL、Redis 与一般 ubuntu 下的安装一样。

NodeJS

使用的官方软件包安装:Installing Node.js via package manager | Node.js
在挂载的其他分区进行操作时,好像对分区的文件系统有要求,我试了在 exFAT 系统上 npm install 失败,需要加 --no-bin-link,并且之后 npm run dev 依然出错(Laravel 项目),换用 NTFS 文件系统的盘则一切正常。
另外 PhpStorm 的 Node.js and NPM 设置里可以选择 WSL 的 node。

IDE 支持

  • 系统自带了 python 3.6.5,可以以 ssh 的方式和 PyCharm 配合。
  • Clion 支持 WSL 里的 cmake、g++等,在 windows 系统编写 Linux 下的 c/c++ 程序丝滑流畅(File | Settings | Build, Execution, Deployment | Toolchains)。
  • PyCharm 以 ssh 的形式支持 WSL 里的 PHP(ssh 远程 composer 暂不支持)。

其他

zsh、lrzsz 安装和一般的 ubuntu 系统无异。

PATH 环境变量

我在 windows 下安装了 visual studio code,偶然发现可以在 bash 里输 code 直接启动,windows 版本的 code 也有启动脚本

➜  ~ which code
/mnt/c/Program Files/Microsoft VS Code/bin/code

原来子系统的 bash.exe 会将 windows 系统的path变量加到自己的 path 里面,意味着你在 bash 里输入 cmd.exe 时,可以“穿越”到 windows 的 cmd 里。因为大部分 windows 应用以exe 结尾,所以一般不会和 linux 系统里的命令冲突。也可以通过注册表禁用这一功能:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lxss]
"AppendNtPath"=dword:00000000

更多讨论见:https://github.com/Microsoft/WSL/issues/1640

代理

可以共用 windows 系统的代理,比如在 windows 下运行了 ss 客户端后,可以设置命令别名:

alias proxy="export ALL_PROXY=socks5://127.0.0.1:1080"
alias unproxy="unset ALL_PROXY"

服务自启动

没有 systemctl ,服务启动/停止用 service xxx start|stop,Linux 下添加服务自启动的方式也无效,需要在启动 bash.exe 的时候加参数。后来我翻了 issue,找到了这个启动脚本:wsl-autostart
作者提供的设置是加在了系统级别的自启动,我换到了用户级别,即注册表地址是:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run,其他地方照着 README 操作即可,注意在将服务加到 commands.txt 之前,要先安装好服务并确认路径,否则遇到不存在的服务,排在后面的服务项会启动不了。
WSL 系统不会开机启动,因此我还将 ubuntu 应用加到了开机启动:将ubuntu 快捷方式固定到开始屏幕,再拖动到桌面,再拖动到 C:\Users\t\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup

wsl.conf

/etc/wsl.conf 文件里面可以配置各种运行参数,文件不存在可创建。这里将windows 磁盘挂载在根目录而不是默认的 /mnt/ 目录:

    [automount]
    enabled = true
    root = /
    options = "metadata,umask=22,fmask=11"
    mountFsTab = false

问题

docker container 无法使用

docker 服务端运行需要 linux 内核,目前无解。可以在 windows 系统安装 Docker for Windows,use windows containers,在 WSL 里正常安装 docker-ce,连接到 windows 里的服务端。注意:windows 10 专业版才带有 Hyper-V,家庭版没有所以装不了 Docker for Windows。

elasticsearch 服务无法自启动

上述服务自启动的方法不适用于包安装的 elasticsearch( /etc/init.d/elasticsearch ),原因未知。

软链接

IDE 不能识别 WSL 下创建的软链接。

ESLint

ESLint 不能使用 WSL 下的 node,仍然要安装 windows 版的node。

npm run watch 失败

用 windows 下的IDE,wsl 的终端运行 npm run watch 会失败,只能在 windows 终端运行,windows 下 node 安装不可避。

ssh 连上时提示异常

   => There were exceptions while processing one or more plugins. See
     /var/log/landscape/sysinfo.log for more information.

/var/log/landscape/sysinfo.log 里的异常日志:

ERROR    Network plugin raised an exception.
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/landscape/sysinfo/sysinfo.py", line 99, in run
    result = plugin.run()
  File "/usr/lib/python3/dist-packages/landscape/sysinfo/network.py", line 32, in run
    for info in self._get_device_info():
  File "/usr/lib/python3/dist-packages/landscape/lib/network.py", line 181, in get_active_device_info
    speed, duplex = get_network_interface_speed(sock, interface)
  File "/usr/lib/python3/dist-packages/landscape/lib/network.py", line 261, in get_network_interface_speed
    raise e
  File "/usr/lib/python3/dist-packages/landscape/lib/network.py", line 253, in get_network_interface_speed
    fcntl.ioctl(sock, SIOCETHTOOL, packed)  # Status ioctl() call
OSError: [Errno 22] Invalid argument

解决方法,修改(创建)配置文件(/etc/landscape/client.conf),禁用 landscape-sysinfo 的 Network plugin:

[sysinfo]
exclude_sysinfo_plugins = Temperature, Network

http://manpages.ubuntu.com/manpages/cosmic/man1/landscape-sysinfo.1.html

小结

WSL 已堪用,以后一定会越来越完善,值得一搞。