惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Check Point Blog
GbyAI
GbyAI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
U
Unit 42
美团技术团队
NISL@THU
NISL@THU
C
Cisco Blogs
SecWiki News
SecWiki News
N
Netflix TechBlog - Medium
Forbes - Security
Forbes - Security
Cloudbric
Cloudbric
雷峰网
雷峰网
T
Tailwind CSS Blog
博客园 - 司徒正美
The Register - Security
The Register - Security
L
LangChain Blog
S
Security Affairs
Hacker News - Newest:
Hacker News - Newest: "LLM"
B
Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
Threat Research - Cisco Blogs
I
InfoQ
S
Schneier on Security
L
Lohrmann on Cybersecurity
量子位
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Martin Fowler
Martin Fowler
Schneier on Security
Schneier on Security
F
Fortinet All Blogs
TaoSecurity Blog
TaoSecurity Blog
K
Kaspersky official blog
Google DeepMind News
Google DeepMind News
Cisco Talos Blog
Cisco Talos Blog
PCI Perspectives
PCI Perspectives
Attack and Defense Labs
Attack and Defense Labs
WordPress大学
WordPress大学
Microsoft Azure Blog
Microsoft Azure Blog
H
Help Net Security
Project Zero
Project Zero
The GitHub Blog
The GitHub Blog
D
Docker
N
News | PayPal Newsroom
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
H
Hacker News: Front Page
云风的 BLOG
云风的 BLOG
Microsoft Security Blog
Microsoft Security Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 聂微东
Webroot Blog
Webroot Blog
MongoDB | Blog
MongoDB | Blog

青空之蓝

[青空之蓝-2023] - 色彩 | 青空之蓝 [青空之蓝-2022] - 平静 | 青空之蓝 [青空之蓝-2021] - 远望 | 青空之蓝 浅谈垃圾回收 | 青空之蓝 浅谈泛型擦除 | 青空之蓝 浅谈单点登录 | 青空之蓝 使用 Kotlin 编写 Spring 测试 | 青空之蓝 设计模式系列文章 | 青空之蓝 从零实现一个 Java 微框架 - IoC | 青空之蓝 从零实现一个 Java 微框架 - 前言 | 青空之蓝 浅谈 JVM:类加载 | 青空之蓝 浅谈 IO | 青空之蓝 浅谈并发:synchronized & ReentrantLock | 青空之蓝 浅谈并发:CAS & AQS | 青空之蓝 浅谈并发:ThreadLocal | 青空之蓝 浅谈并发:三大特性 | 青空之蓝 浅谈组合注解 & 注解别名 | 青空之蓝 [青空之蓝-2020]-迷茫 | 青空之蓝 Java 系列文章 | 青空之蓝 HTTP 系列文章 | 青空之蓝 浅谈 EatWhatYouKill | 青空之蓝 浅谈可扩展线程池 | 青空之蓝 聊聊写框架 | 青空之蓝 聊聊现状-[2020-09] | 青空之蓝 浅谈并发:锁 | 青空之蓝 浅谈并发:基础 | 青空之蓝 浅谈缓存 | 青空之蓝 无须定义类,Spring 快速注入 Json 参数 | 青空之蓝 浅谈 Proxy 和 Aop | 青空之蓝 从零实现一个 PHP 微框架 - 初始化请求 | 青空之蓝 为 Vue3 添加一个简单的 Store | 青空之蓝 从零实现一个 PHP 微框架 - 服务提供者 | 青空之蓝 浅谈浏览器Event Loop [更新] | 青空之蓝 从零实现一个 PHP 微框架 - Bootstrap 启动加载 | 青空之蓝 从零实现一个 PHP 微框架 - IoC 容器 | 青空之蓝 从零实现一个 PHP 微框架 - PSR & Composer | 青空之蓝 从零实现一个 PHP 微框架 - 前言 | 青空之蓝 MVVM 简单实现 | 青空之蓝 浅谈 DI 和 IoC | 青空之蓝 中间件实现 [PHP] | 青空之蓝 告别 Windows 终端的难看难用,打造好用的 PowerShell | 青空之蓝 VSCode Java输出中文乱码问题解决[更新] | 青空之蓝 浅谈浏览器渲染 | 青空之蓝 Vue-Cli@2 项目迁移日志 | 青空之蓝 Laragon & Scoop 集成踩坑记录 | 青空之蓝 「一行代码」优雅管理 Windows 软件 | 青空之蓝 [青空之蓝-2019]-年度总结 | 青空之蓝 为Vue添加简单的Store | 青空之蓝 为React添加简单的Store | 青空之蓝 为Vuex添加同步Action | 青空之蓝 浅谈B+树 | 青空之蓝 浅谈跳表 | 青空之蓝 浅谈数据库索引 | 青空之蓝 MySQL事务隔离 | 青空之蓝 算法复杂度分析(1) | 青空之蓝 一年来的经验总结 | 青空之蓝 Acrylic - VSCode Extension | 青空之蓝 ace编辑器设置惯性滚动 | 青空之蓝 Java二叉树实现 | 青空之蓝 Java图实现 | 青空之蓝 为apt方式安装的nginx重新编译增加WebDAV | 青空之蓝 XK-Editor - 一个支持富文本和Markdown的编辑器 | 青空之蓝 JS生成列表树 | 青空之蓝 Laravel生成目录树 | 青空之蓝 XK-Note - 集各种神奇功能的云笔记 | 青空之蓝 PHP GD生成验证码 | 青空之蓝 PHP GD图片处理[转换格式-水印-缩略图] | 青空之蓝 Origami - 简洁轻快的WordPress主题 | 青空之蓝 为WordPress启用WorkBox | 青空之蓝 [青空之蓝-2018]-年度总结 | 青空之蓝 VSCode Java手动导入jar和源码包 | 青空之蓝 Windows IP变化自动发送邮件 | 青空之蓝 C链表实现重制版 | 青空之蓝 C 结构体的定义和使用 | 青空之蓝 图的搜索(遍历) - BFS & DFS | 青空之蓝 Java链表实现 | 青空之蓝 C 快速排序 | 青空之蓝 C 插入排序 | 青空之蓝 C 归并排序 | 青空之蓝 C语言链表实现 | 青空之蓝 VSCode配置Java调试环境[Windows] | 青空之蓝 C 选择排序 | 青空之蓝 C 冒泡排序 | 青空之蓝 VSCode配置PHP调试环境[Windows] | 青空之蓝 VSCode配置C/C++ GDB调试环境[Windows] | 青空之蓝 WordPress友情链接模板 | 青空之蓝 Intel Optane 傲腾内存体验 | 青空之蓝 Mysql双机热备实战 | 青空之蓝 博客一年记录 | 青空之蓝 为WordPress启用Service Worker | 青空之蓝 Bing每日一图API | 青空之蓝 iframe延迟加载 | 青空之蓝 写在2018年高考前 | 青空之蓝 The Fox主题汉化分享 | 青空之蓝 [青空之蓝-2017]-崭新 | 青空之蓝 本博客评论规则 | 青空之蓝 世界,您好! | 青空之蓝
WSL2 踩坑记录 | 青空之蓝
Otstar Lin · 2020-06-28 · via 青空之蓝

前言

前不久 Windows 20H1 正式推送了,我们终于可以用上 WSL2 了,博主因为是 Release 通道的 Insider,所以比其他用户早升级到 20H1,由于之前比较忙,所以一直没折腾 WSL2,直到前天考完了试,并且我之前部署的 Ubuntu 虚拟机总是出现一些问题,于是就打算试试 WSL2。

安装

准备环境

由于 WSL2 使用的是 Hyper-V 虚拟平台,所以我们需要先开启虚拟机平台,使用以下命令开启,或者也可以使用 Windows 的界面进行设置。

Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform

设置完成后重启下 Windows。

准备发行版

重启完成后我们可以先使用 wsl -l 查看已经安装的 WSL 发行版。

由于 WSL2 和 WSL1 可以共存,如果你想日常继续使用 WSL1,只将 WSL2 用于 Docker 等用途的话,我建议你复制一份,然后将其转成 WSL2,就如上面的截图一样(Ubuntu 是 WSL1,Ubuntu-WSL2 是 WSL2)。

复制 WSL 发行版的方法如下:

首先安装 LxRunOffline,Scoop 可以使用 scoop install lxrunoffline 安装。其他的安装方式这里就不写了,具体请自行查看。

使用 LxRunOffline 复制的方式很简单,使用以下命令即可:

lxrunoffline d -n <要复制的发行版> -d <复制后存储的路径> -N <复制后发行版的名>
lxrunoffline d -n <要复制的发行版> -d <复制后存储的路径> -N <复制后发行版的名>

当然有时候我们会使用新建的发行版来用于 WSL2,这时就可以用 LxRunOffline 导入新的发行版,也可以用 Microsoft Store 安装。

切换 WSL 版本

有了要转换的发行版后我们就可以用以下命令将 WSL1 转换成 WSL2 了。

wsl --set-version <发行版> <版本(1,2)>

# 设置默认创建的 WSL 版本,按需设置
wsl --set-default-version <版本(1,2)>
wsl --set-version <发行版> <版本(1,2)>

# 设置默认创建的 WSL 版本,按需设置
wsl --set-default-version <版本(1,2)>

等待其切换完成,切换完成后就可以通过 wsl -d <发行版> 进入到 WSL 中,此时 WSL2 的安装就完成了。

初始化 WSL2

对于初始设置 Apt 镜像,安装基础应用,Docker,Systemd,Zsh 的脚本我已经制作好了,并发布到了 Github 上,你可以直接使用此脚本完成对 WSL2 的一些初始化操作。

使用此脚本安装的 Docker 已经预先配置好了tcp:2375端口,Windows 下只需设置 DOCKER_HOST 的环境变量就可以无痛使用 Docker 和 Docker-Compose,而无需安装 Docker for Windows,同时在 WSL1 中也可以通过这种方式使用 WSL2 中的 Docker(不过一般也不需要,WSL1/2 中可以直接使用 Windows 下的命令和程序。

注意: 在某些情况下,可能会出现 2375 端口处于监听状态,但是 Windows 无法连接的情况,所以博主建议使用 socat 来暴露 docker 的管理端口,具体查看 docksal/service-socat

同时,本脚本会设置一个启动时进行一些设置的 shell 脚本,具体功能如下:

自动设置 hosts,由于 WSL2 中目前还无法实现使用 localhost 访问 Windows 下的服务,所以需要通过 hosts,或者 IP 来间接访问 Windows 的服务,但是由于 WSL2 的 Hyper-V 交换机在每次重启的时候都会重设 IP,这就导致了 hosts 无法设置成静态的,不然一重启就需要重新设置了。解决这个问题的方案是在每次进入 WSL2 的时候自动从 /etc/resolved.conf 中获取 Windows 的 IP,然后将该 IP 设置到 hosts 中,同时删除旧的 hosts。(默认设置的域名是 h.test

设置WSL_HOST环境变量,如果不想使用 hosts 的域名,也可以使用 WSL_HOST 来访问 Windows。

设置DISPLAY环境变量,通过该环境变量,我们就可以将 Linux GUI 应用转发到 Window 下的 X Server。

启动 systemd,由于 WSL2 依旧是使用 init 进程,而非 systemd,所以我们无法使用 systemctl,这对 WSL2 的使用产生了很多的限制,不过我们可以通过一些手段来启动 systemd,具体见 ubuntu-wsl2-systemd-script。本脚本对其进行了一些修改以适应本脚本。

一些使用技巧

停止 WSL2:wsl --shutdown wsl -t <发行版>

备份:wsl --export <分发版> <文件名>

恢复:wsl --import <发行版> <安装位置> <文件名> [--version <版本>]

设置默认登录用户:lxrunoffline su -n <发行版> -v <UID>

卸载:lxrunoffline ui -n <发行版>

移动:lxrunoffline move -n <发行版> -d <路径>

复制:lxrunoffline d -n <要复制的发行版> -d <复制后存储的路径> -N <复制后发行版的名>

Windows 目前已经可以使用 localhost 访问 WSL2 了,不过由于 Hyper-V 端口映射的一些问题,可能在 Windows 下会出现没有使用的端口也提示占用的问题并且 netcat 也未显示,这是因为 WSL2 的动态端口设置有点问题,WSL2 的动态端口是从 1024 开始映射的,可以用以下的命令调整到高一点的端口。

netsh int ip set dynamicport tcp start=49152 num=16384
netsh int ip set dynamicport tcp start=49152 num=16384

Docker for Windows 似乎会调整 WSL2 Hyper-V 交换机的类型,这会导致 Windows 无法使用 localhost 访问 WSL2,解决的方案是将 WSL2 的 Hyper-V 交换机调回内部网络

由于 Hyper-V/WSL2 的网络不属于防火墙的专用组,所以部分应用会因为防火墙的问题而无法访问 Windows 下的端口,解决方案是使用以下的命令添加防火墙规则,同时删除阻止规则。(由于 Window 防火墙阻止规则的优先级大于允许,这会导致以下设置的规则无效)

New-NetFirewallRule -DisplayName "WSL" -Direction Inbound  -InterfaceAlias "vEthernet (WSL)"  -Action Allow
New-NetFirewallRule -DisplayName "WSL" -Direction Inbound  -InterfaceAlias "vEthernet (WSL)"  -Action Allow

如果你一定需要使用静态 IP,那么也可以用以下的命令另外添加静态 IP。(重启失效)

netsh interface ip add address "vEthernet (WSL)" 192.168.50.1 255.255.255.0
wsl -d Ubuntu-WSL2 -u root ip addr add 192.168.50.199/24 broadcast 192.168.50.255 dev eth0 label eth0:1
netsh interface ip add address "vEthernet (WSL)" 192.168.50.1 255.255.255.0
wsl -d Ubuntu-WSL2 -u root ip addr add 192.168.50.199/24 broadcast 192.168.50.255 dev eth0 label eth0:1

在 Windows 中要使用 WSL 中的应用我们可以创建一个 Proxy 脚本来代理调用 WSL 的应用,具体创建的方式如下,创建好后就可以用这个在 Windows 下执行该脚本,相当于在 WSL 中执行命令:

# powershell
wsl -- docker $args

# cmd
@echo off
wsl.exe -c "docker %*"
# powershell
wsl -- docker $args

# cmd
@echo off
wsl.exe -c "docker %*"

在 WSL2 的 Shell 中使用 docker-compose 你可能也会遇到这个问题:

Traceback (most recent call last):
  File "bin/docker-compose", line 6, in <module>
  File "compose/cli/main.py", line 72, in main
  File "compose/cli/main.py", line 128, in perform_command
  File "compose/cli/main.py", line 1078, in up
  File "compose/cli/main.py", line 1074, in up
  File "compose/project.py", line 548, in up
  File "compose/service.py", line 361, in ensure_image_exists
  File "compose/service.py", line 1250, in pull
  File "compose/progress_stream.py", line 102, in get_digest_from_pull
  File "compose/service.py", line 1215, in _do_pull
  File "site-packages/docker/api/image.py", line 396, in pull
  File "site-packages/docker/auth.py", line 48, in get_config_header
  File "site-packages/docker/auth.py", line 324, in resolve_authconfig
  File "site-packages/docker/auth.py", line 235, in resolve_authconfig
  File "site-packages/docker/auth.py", line 262, in _resolve_authconfig_credstore
  File "site-packages/docker/auth.py", line 287, in _get_store_instance
  File "site-packages/docker/credentials/store.py", line 25, in __init__
docker.credentials.errors.InitializationError: docker-credential-desktop.exe not installed or not available in PATH
[2037] Failed to execute script docker-compose
Traceback (most recent call last):
  File "bin/docker-compose", line 6, in <module>
  File "compose/cli/main.py", line 72, in main
  File "compose/cli/main.py", line 128, in perform_command
  File "compose/cli/main.py", line 1078, in up
  File "compose/cli/main.py", line 1074, in up
  File "compose/project.py", line 548, in up
  File "compose/service.py", line 361, in ensure_image_exists
  File "compose/service.py", line 1250, in pull
  File "compose/progress_stream.py", line 102, in get_digest_from_pull
  File "compose/service.py", line 1215, in _do_pull
  File "site-packages/docker/api/image.py", line 396, in pull
  File "site-packages/docker/auth.py", line 48, in get_config_header
  File "site-packages/docker/auth.py", line 324, in resolve_authconfig
  File "site-packages/docker/auth.py", line 235, in resolve_authconfig
  File "site-packages/docker/auth.py", line 262, in _resolve_authconfig_credstore
  File "site-packages/docker/auth.py", line 287, in _get_store_instance
  File "site-packages/docker/credentials/store.py", line 25, in __init__
docker.credentials.errors.InitializationError: docker-credential-desktop.exe not installed or not available in PATH
[2037] Failed to execute script docker-compose

此时你只需要运行以下的命令即可:

rm ~/.docker/config.json
rm ~/.docker/config.json

无意间发现的小特性

如果你看过 WSL 导出的系统你会发现导出的是 rootfs,而碰巧 docker 导出的容器也是 rootfs,所以理论上是可以通用的,而且 WSL 本来就可以导入 docker 的基础系统(如 Ubuntu 镜像),那么从基础系统上构建的镜像也是可以运行在 WSL 上的。

由于从 DockerHub 上拉取的是分层的镜像,所以我们需要创建成容器后再导出。

docker run -d --name nginx nginx
docker export -o /mnt/f/nginx.tar nginx
docker run -d --name nginx nginx
docker export -o /mnt/f/nginx.tar nginx

导出后我们就取得了 nginx 容器的 rootfs,然后通过 lxrunoffline 导入这个 rootfs 到 WSL

lxrunoffline i -n nginx -d F:\wsl\nginx -f F:\nginx.tar
wsl --set-version nginx 2 # 可选
lxrunoffline i -n nginx -d F:\wsl\nginx -f F:\nginx.tar
wsl --set-version nginx 2 # 可选

导入后就可以启动了

博主我稍微测试了下,运行是没有问题的,不过有可能会有坑,如果你不想在 WSL 里跑 docker 的话也可以考虑试试这个方案。

结语

WSL2 其实我们可以把它看成是一个轻量的虚拟机平台,介于 Docker 和 VM 间的存在,WSL2 相比于传统的 VM,它的启动速度飞快,同时占用更小,而且自动设置了端口映射和目录挂载,同时导入发行版的速度也比从头安装系统快出许多,我试过导入一个 Ubuntu Core 的镜像,并转成 WSL2,算上打字的延迟,只需要 28s。

相比 Docker 虽然差了很多,不过偶尔需要使用非 Docker 的 Linux,也不再需要等待漫长的安装了。

不过 WSL2 目前还不够完善,还有许多的问题,比如 WSL2 访问 Windows 的问题就挺难受的,还有 export import 的效率不如 VMware 和 VBox 的快照等等。

希望微软能越做越好吧,现在 WSL 已经支持 GPU 加速了,那么下一个功能会是什么呢?好奇.jpg

WSL2 踩坑记录

https://blog.ixk.me/post/wsl-2-recording
  • 许可协议

    BY-NC-SA

  • 本文作者

    Otstar Lin

  • 发布于

    2020/06/28

转载或引用本文时请遵守许可协议,注明出处、不得用于商业用途!

从零实现一个 PHP 微框架 - 服务提供者浅谈浏览器Event Loop [更新]