Linux 的魅力难以抵挡。更好的服务器,更强大的命令行工具,更开放、更丰富、更有活力的生态,吸引着越来越多的开发者,也吸引着走向云端、走向开放、拥抱新时代的微软。即使是 Windows 也必须服务于微软的新战略。

Windows 仍然是最重要的桌面操作系统之一。很多人像我一样,不想折腾,离不开 Windows,想在 Windows 环境下使用 Linux,怎么办?

本文告诉你如何用上微软最新的解决方案,可以在不离开 Windows 的情况下,了解 Linux,使用 Linux,爱上 Linux。

WSL

WSL 是 Windows Subsystem for Linux 的缩写,顾名思义,就是 Windows 系统的 Linux 子系统。WSL 是一个能在 Windows 上运行原生 Linux 二进制可执行文件的兼容层。WSL 作为内置组件搭载在 Windows 1607 后的 Windows 系统中。

2019年6月13日, Windows 10 发布了 Build 18917 预览版, WSL2 可以使用了。由于 WSL2 的架构有了重大改变,WSL1 被暂时保留,将与 WSL2 共存。WSL2 将作为标准组件成为即将发布的 Windows 10 Version 2004 的一部分(预计2020年5月发布)。

WSL2 基于 Hyper-V,使用真正的 Linux 内核,文件系统为 ext4,效率有极大的提升。特别是,WSL2 能跑 Docker 了,Windows 家庭版因此可以愉快地运行 Docker,不用折腾了。

安装 WSL2

WSL2 支持全系 Windows 10 包括家庭版,但仅在 Windows 10 18917 或更高版本中可用。

首先,Win+R 执行 winver 检查系统版本,如果版本号低于 18917,请更新操作系统,加入 Windows预览体验计划

更新操作系统

Win+X 设置 > 更新和安全 > Windows更新

加入 Windows 预览体验计划

Win+X 设置 > 更新和安全 > Windows预览体验计划

启用虚拟机平台和 Linux 子系统

使用管理员模式打开 PowerShell 运行如下命令:

1
2
3
4
5
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
# 或
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform

运行完成后,请重启电脑完成安装。

安装 Linux 发行版

设置发行版为 WSL2

重启后执行 wsl --set-default-version 2 使任何新安装的发行版初始化为 WSL2。

可能需要下载更新内核组件 - https://aka.ms/wsl2kernel

安装启动 Linux 发行版

打开 Microsoft Store:

  • 搜索 Ubuntu-18.04 获取安装;
  • 搜索 Windows Terminal 获取安装;

启动 Windows Terminal,执行 wsl 启动 Ubuntu-18.04 终端。

首次启动需要设置用户名和密码,初始目录是:我的文档。

配置 Ubuntu 终端支持中文

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 安装中文支持包
# locale -a  # 查看已安装字体
sudo apt install -y language-pack-zh-hans

# 将默认locale改为中文,开启中文locale支持,然后重启终端
sudo sed -i "s/LANG=C.UTF-8/LANG=zh_CN.UTF-8/g" /etc/default/locale
sudo sed -i "s/# zh_CN.UTF-8 UTF-8/zh_CN.UTF-8 UTF-8/g" /etc/locale.gen
sudo locale-gen

# 安装中文手册(可选)
sudo apt install manpages-zh

WSL 命令与使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
wsl -l  # 列表已安装的 Linux 发行版
wsl -l -v  # 列表已安装发行版名称、状态与WSL版本

wsl -d <distro_name>  # 启动指定发行版
wsl -t <distro_name>  # 终止指定发行版
wsl -s <distro_name>  # 设置默认启动的发行版

wsl dmesg  # 查看启动信息
wsl -d <distro_name> -u root  # 以指定用户启动发行版
wsl -d <distro_name> -u root -e uname -a # 启动发行版并执行命令

wsl --shutdown  # 终止所有发行版和 WSL2 虚拟机
wsl --unregister <distro_name>  # 注销指定发行版

wsl --set-default-version 2  # 设置发行版的默认WSL版本
wsl --set-version <distro_name> 2  # 转换发行版的WSL版本

如果C盘空间有限,可以移动发行版虚拟机文件 ext4.vhdx 的位置。

使用管理员权限启动 PowerShell,参考如下命令:

1
2
3
4
wsl --export Ubuntu-18.04 D:\backup\ubuntu-18.04-wsl2.tar
wsl --import Ubuntu-18.04 D:\HyperV\ubuntu-wsl D:\backup\ubuntu-18.04-wsl2.tar
# wsl --import Ubuntu D:\HyperV\ubuntu-wsl D:\backup\ubuntu-18.04-wsl2.tar
# wsl --unregister Ubuntu-18.04

以上操作可备份、恢复已安装的 Linux 发行版,结合注销操作可修改发行版的名称。

互操作性

VSCode 远程开发

在 VSCode 中安装 Remote Development 或 Remote - WSL 扩展,完成后单击左下角连线图标,选择 Remote-WSL: New Window, 打开新窗口并连接 WSL 默认发行版,然后就可以打开 Linux 发行版中的项目目录或文件,使用 VSCode 进行 Linux 开发了。也可以直接在发行版目录中使用 code . 打开目录。

在正式进行跨平台开发之前,请务必统一字符集为 UTF-8,文本换行符为 LF (\n)。

参考:Git 安装配置VSCode 安装配置

文件互访及其它互操作

WSL2 虽然使用了虚拟化架构,但可以与宿主机无缝共享文件,比双系统和传统虚拟机方便。

Linux 使用 /mnt/盘符/ 访问Windows磁盘文件,Windows 通过 \\wsl$\发行版\ 访问Linux根目录。

  • 可以在 WSL2 中执行 .exe 命令,如 explorer.exe . (注意是 Windows 路径)
  • 可以为 .exe 命令设置一个别名,如 alias start='cmd.exe /c start'
  • 可以在 Windows 中直接执行 Linux 命令,如 wsl ls -al ~/
  • 可以使用 localhost 访问 Linux 发行版中的服务。

Docker

Docker 是一个开源的应用容器引擎,是 Linux 容器技术的代表,是容器时代的开创者。Docker 利用 Linux 核心的资源分离机制(cgroups)和命名空间(namespaces)来建立独立的软件容器(containers),可以实现应用打包部署代码化、自动化,应用环境一致化、轻量化。可以使用Docker打包应用及其依赖,通过Docker平台分发、部署到任何Docker引擎中运行,实现“一次构建,处处运行”。

Docker 改变了应用开发、测试、部署、交付的方式与流程,支持持续集成、持续部署、自动化测试,支持 DevOps、微服务、弹性云计算,在国内外IT大厂中得到了广泛应用。

安装 Docker

Docker 可以在 Linux 虚拟机中运行。在 Windows 环境下运行 Docker,可以使用 Linux 虚拟机、Docker Desktop 等工具,现在,可以使用 WSL2(Docker Desktop 现已支持 WSL2)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 执行 wsl 启动 ubuntu 分发, cd 切换到用户家目录,下载脚本,执行安装
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
docker -v

# sudo groupadd docker
# cat /etc/group | grep docker
# cat /etc/passwd | grep $USER

# 添加当前用户到 docker 组,启动服务
sudo usermod -aG docker $USER
sudo service docker start
docker info

# 运行 Docker 版 Hello World
docker run hello-world

# 安装 docker compose
sudo curl -L https://github.com/docker/compose/releases/download/`curl -s https://github.com/docker/compose/tags | grep "<a href=\"/docker/compose/releases/tag" | sed -r 's|.*([0-9]+\.[0-9]+\.[0-9]+(-rc[0-9])?).*|\1|p' | head -n 1`/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
# sudo curl -L "https://github.com/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# 或安装 docker compose - Python 版
sudo apt-get install -y python3 python3-pip
pip install --user docker-compose

# 确认 docker compose 安装
docker-compose --version

启动 Docker 服务

Linux 发行版普遍采用 systemd 管理后台服务。由于在 WSL2 中 systemd 没有作为系统 init (PID 1) 启动,导致 Docker 等后台服务无法自动启动。官方应该清楚这个问题,但对这个 Issue 没有给出有效方案,所以有人在GitHub上给出了解决办法<1><2>,也可以利用Windows的启动机制编写开机启动脚本。

Win+R 输入 shell:startup 进入启动目录,创建一个 .vbs 脚本文件,参考内容如下:

1
2
3
4
5
6
7
WScript.sleep 5000
Set ws = CreateObject("WScript.Shell")
ws.run "wsl -d ubuntu-18.04 -u root /etc/init.d/docker start",vbhide,FALSE
'ws.run "wsl -d ubuntu-18.04 -u root /etc/wslstart",vbhide,FALSE
'ws.run "wsl -d ubuntu-18.04 -u root /bin/true",vbhide,FALSE
Set ws = Nothing
WScript.quit

还可以通过 Windows 计划任务实现开机启动 WSL2 和相关服务。

必要时,在 Linux 端配合编写启动脚本: sudo vim /etc/wslstart

1
2
3
#!/bin/sh
sudo service docker start
docker start postgres
1
2
3
4
5
# 给脚本添加执行权限
sudo chmod +x /etc/wslstart
# or
echo "service docker status >/dev/null || sudo service docker start" >> $HOME/.bashrc
echo "docker start postgres" >> $HOME/.bashrc

虚拟机

虚拟机是对物理机(硬件)的虚拟化,可将一台设备虚拟为多台设备。可以在虚拟机中运行任何操作系统。容器是对操作系统的虚拟化,是一种轻量级的虚拟化技术。容器可以运行在虚拟机中。

虚拟机提供了完整的操作系统,体积大,速度慢,但隔离程度高。容器只是提供应用执行环境,体积小、速度快、资源效率高,但隔离性没有虚拟机好。

特性 虚拟机 容器
隔离级别 操作系统级 进程级
镜像大小 GB-TB KB-MB
启动时间 分钟级 秒级
资源配置 5-15% 0-5%
集群规模 上百 上万

Windows 内置 Hyper-V,还有免费的 VirtualBoxVMware Player(VMware Workstation的子集)。下载 Linux 发行版的 ISO 文件,然后使用虚拟机挂载 ISO 文件,就可以将其安装在虚拟机中,像在标准计算机上一样。Windows Home 可以使用 WSL2,但完整的 Hyper-V 仍不可用。

Hyper-V 属于 Type-1 hypervisor,VirtualBox、VMware Workstation 属于 Type-2 hypervisor。Type-1 hypervisor 在裸机上运行,相当于操作系统;Type-2 hypervisor 在操作系统上运行,相当于应用程序。当启用 Hyper-V 时,Windows 将成为一台特殊的虚拟机,硬件虚拟化支持在这台虚拟机中变成不可用。

2018年,微软开放了 Windows Hypervisor Platform API,第三方虚拟化提供商可以使用这些 API 使其软件与 Hyper-V 兼容。此刻,最新版的 VirtualBoxVMware Workstation 已经能与 Hyper-V 同时使用了。

必要的话,可设置系统启动菜单,添加开关 Hyper-V 的菜单项,来切换虚拟机环境。

以管理员模式打开 PowerShell, 执行 cmd, 执行以下命令:

1
2
3
4
bcdedit /copy {current} /d "Windows 10 Hyper-V off"
bcdedit /set {复制前面命令生成的GUID} hypervisorlaunchtype off
bcdedit /copy {current} /d "Windows 10 Hyper-V auto"
bcdedit /set {复制前面命令生成的GUID} hypervisorlaunchtype auto

执行 Win+R: msconfig,切换到引导标签页查看启动项。

MSYS2

MSYS2 是基于 MinGW-w64 和 Cygwin 的 Windows 软件开发平台。集成了优秀的软件包管理器 Pacman,有活跃的开发者和用户组,有大量预编译的软件包。配合 ConEmu(或 Cmder)是 Windows 环境下最好的类 Linux 开发环境,没有之一。Git for Windows 官方发行版使用了 MSYS2 及其 bash 环境。

MSYS2 的产生体现了开源软件的价值观,相关项目简介如下:

Cygwin

Cygwin 是运行于Windows平台的POSIX“子系统”,提供Windows下的类Unix环境,提供将Linux应用“移植”到Windows平台的开发环境。

Cygwin 提供了一套抽象层 dll,用于将 POSIX 调用转换成 Windows API 调用。由于它的模拟层实现了相当良好的 POSIX 兼容性,许多重要的 Linux/BSD 应用移植到了 Cygwin(源码移植,非原生)。

Cygwin 中既可以运行 Cygwin 应用(依赖模拟层),又可以运行 Windows 应用,传递给应用的路径会经过模拟层变换,以保证程序运行不会出错。

MinGW & MSYS

MinGW (Minimalist GNU for Windows) 是用于开发 Windows 应用的 GNU 开发环境。编译出来的应用不依赖第三方模拟层的支持,其运行时为大部分 Windows 标配的 msvcrt(故称原生 Windows 应用)。MinGW 支持 GCC 支持的多数编程语言,因此被许多 Linux 上发展起来的开发工具选择为 Windows 版本的默认编译器,例如 CodeBlocks、DevC++。MinGW 工具链也存在于 Linux、BSD 甚至 Cygwin 下。

MSYS 是 MinGW 开发者从 Cygwin 早期版本创建的一个分支,以基本的 Linux 工具为主,用于提供类 Unix 环境,辅助 Windows 版 MinGW 进行命令行开发。

MinGW-w64 & MSYS2

MinGW-w64 是新一代的 MinGW,提供了更完整的 Win32 API 实现,支持 64 位应用开发,可以生成 32 位和 64 位可执行文件,甚至支持 32 位 host 编译 64 位应用以及反过来的“交叉”编译。MinGW-w64 包括GNU编译器(GCC),GNU工具(汇编器,链接器,档案管理器),一组可自由分发的 Windows 专用头文件和可使用 Windows API 的静态导入库,GNU调试器的 Windows 本机版本以及其他实用程序。

由于 MinGW 和 MSYS 更新缓慢,Alex 等人建立了 MSYS2 项目。MSYS2 同样 fork 自 Cygwin,但使用了较新版本,完全独立于 MSYS,并且集成了 MinGW-w64 和 Arch Linux 的软件包管理器 Pacman。

MSYS2 的三个子系统

MSYS2 包含三个子系统:基于 Cygwin 的 msys2, 基于 MinGW-w64 的 mingw32 和 mingw64。每个子系统都提供了自己的本机(即target = host)编译器工具链,分别在 msys2-devel,mingw-w64-i686-toolchain 和 mingw-w64-x86_64-toolchain 软件包中。

msys2 移植 POSIX 环境的程序一般更方便,但运行时依赖 POSIX 兼容层(msys-2.0.dll)。如果只是开发 Windows 程序,能用 mingw 就不要用 msys2。当然,msys2 工具跟 GNU 工具配套是没问题的。msys2 不支持64位交叉编译32位,需要独立部署 mingw32 和 mingw64 的开发和运行环境。

mingw 的兼容性和性能都是最好的(注意32位和64位不能混用)。基本原则是开发用的类库和编译器使用 mingw 的,bash 等通用工具安装 msys2 的。一般来说,大多数时间使用 mingw64。

结束语

程序员是软件生态的中坚力量,“讨好程序员”也是大厂战略之一。以微软(3E战略)为例,拥抱开源、收购 GitHub、Microsoft Loves Linux,直至 Windows 内置 Linux 内核。WSL2 配合 Windows Terminal 和 VSCode,体验相当不错。

然而时代不同了。苹果有 iOS 和 macOS,谷歌有 Android、Chrome OS 和 Fuchsia。既然 Edge 可以 Chromium,Windows 可以“双核”,微软会不会开发 Linux 桌面系统呢?

没有比较就没有鉴别,在那一天到来之前,你会考虑原生 Linux 桌面发行版吗?

Manjaro, Linux Mint, Ubuntu, Deepin 都是不错的选择。