故事
故事开始于我需要在 Windows 下用 Jekyll 转化一篇 Markdown 的博文,于是在 Windows 下安装了 Jekyll,其中涉及一些 MSYS2 的安装坑。 接下来想到 MSYS2 其实可以解决 Vibora 的问题,于是将这两个过程中的难点记录一下,再谈谈在 Windows 下使用 Linux 的话题。
本文旨在为正使用 Windows 同时又想使用 Linux 功能的人列举一些可能的途径,本文适用于对 Windows 和 Linux 具备一定了解的人。 另有计划写 Windows、macOS、Linux 操作系统比较的博文,但本文的范围不涉及比较。
Widnows 下用 Jekyll
Jekyll 依赖于 Ruby Runtime 和一些 Gem 包,而 Ruby Runtime 在 Windows 下推荐用于 RubyInstaller, 某些 Gem 包需要本地编译,官方推荐 MSYS2 安装 Windows 上的编译工具链。 因为众所周知的原因,国内安装这些软件时也会遇到一些问题。下面叙述步骤并给予问题的解决办法。
安装 Ruby
运行下载好的 RubyInstaller,基于少一层目录的原因,建议直接安装在根目录下,例如 C:\Ruby25\,并将此目录加入安装目录到 PATH。在最后点击结束按钮后,会提示安装 MSYS2,它用来编译 Ruby 本地包,官方说它的下载由一个全球 CDN 提供,但它在国内的访问真是无力吐槽。
也许你等待龟速网络很久可以将 MSYS2 安装成功,也许你会遭遇反复失败,不知如何是好。但如果你需要使用 Jekyll,而它使用了本地二进制包,那么这个问题是无法跳过的。
安装 MSYS2 的小技巧
如果你跳过了 MSYS2 安装,那么在后续的 gem install 时,会提示:
MSYS2 could not be found. Please run 'ridk install' or download and install MSYS2 manually from https://msys2.github.io/
当你执行 ridk install 时,会显示下载 http://repo.msys2.org/distrib/x86_64/msys2-x86_64-20180531.exe 失败,我的解决办法是用迅雷下载 msys2-x86_64-20180531.exe,并用 IIS 或 Apache 等服务器,在本地配置一个站点下载,这样做需要管理员权限修改 C:\Windows\System32\drivers\etc\hosts 文件,临时加入一行配置:
127.0.0.1 repo.msys2.org
此时确保访问 http://127.0.0.1/distrib/x86_64/msys2-x86_64-20180531.exe 时可以正常下载。那么再次运行 ridk install 时,就会通过本机下载了。
然后,当 msys2-x86_64-20180531.exe 下载完毕时,需要及时把上述 hosts 配置行删除,因为本机并没有 repo.msys2.org 站点下的其他文件。
配置 MSYS2 镜像地址
同时,为了 MSYS2 其他包方便下载,建议配置国内镜像,分别修改下面三个文件,在配置的最上加入 清华大学 与 中科大镜像地址
C:\msys64\etc\pacman.d\mirrorlist.mingw64
##
## 64-bit Mingw-w64 repository mirrorlist
##
## 清华大学软件镜像
Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/x86_64/
## 中科大镜像
Server = http://mirrors.ustc.edu.cn/msys2/mingw/x86_64/
C:\msys64\etc\pacman.d\mirrorlist.mingw32
##
## 32-bit Mingw-w64 repository mirrorlist
##
## 清华大学软件镜像
Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/i686/
## 中科大镜像
Server = http://mirrors.ustc.edu.cn/msys2/mingw/i686/
C:\msys64\etc\pacman.d\mirrorlist.msys
##
## MSYS2 repository mirrorlist
##
## 清华大学软件镜像
Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/msys/$arch/
## 中科大镜像
Server = http://mirrors.ustc.edu.cn/msys2/msys/$arch/
如果你及时删除了 hosts 文件中的配置行,那么 NSYS2 即可以顺利完成安装。
测试 MSYS2 安装是否成功
可以再次运行 ridk install,命令行会打开
RubyInstaller2 for Windows
1 - MSYS2 base installation
2 - MSYS2 system update
3 - MSYS2 and MINGW development toolchain
试试 1、2、3 三个选项,如果全部没有可更新项时,就证明 MSYS2 安装已经成功了。
配置 Gem 镜像地址
对于有价值的开源技术,国内一般都进行了镜像,一般都建议直接使用国内镜像地址。运行下面命令配置镜像
gem sources –r https://rubygems.org/
gem sources -a https://ruby.taobao.org/
运行下面命令查看,并更新
gem sources -l
gem update
安装 Jekyll
下面是官方网站优雅的几行介绍
~ $ gem install bundler jekyll
~ $ jekyll new my-awesome-site
~ $ cd my-awesome-site
~/my-awesome-site $ bundle exec jekyll serve
# => Now browse to http://localhost:4000
有了上面步骤的铺垫,至此,Jekyll 可以优雅的运行了。
关于 Ruby 的感叹
十年前,曾在 Ruby 语言通过 Web 2.0 的需求爆发时,借 Web 敏捷框架 Rails 大红大紫了解过它,对这些年一直没有再有机会使用,如果没有 Rails,Ruby 就不会红,定位于 Python 和 Perl 之间,如今它也许会有所发展,但综合来看,都会逐渐变成先前使用了 RoR 公司的技术遗产,市场上 Ruby 的技术人员也会越来越少,加上它本身并未和现在大前端、移动互联网、大数据、云计算、人工智能、VR等任何一个热点沾边,也不具备后端编译语言的规模成本优势,从系统论视角思考,没有生态,就会走向低谷,但在它擅长的 Web 领域内,还是一种有智慧的解决方案。
相比来说,经常能先于时代的 Python 的好运气并不是偶然,因为重视科研领域,它借着大数据分析和人工智能一飞冲天,如今生态广阔的 Python,相比来说就有着更稳固的护城河,这种就好比持续增长的公司拥有的竞争优势一样,更值得长期看好。所以,下面就说说 Python Web Framework:Vibora
Widnows 下用 Vibora
Vibora 性能闪瞎眼,为了不让 MSYS2 环境浪费,于是尝试是否可以通过 MSYS2 将它运行起来。
MSYS2 安装 python3
首先,打开 MSYS2 运行 python 或 python3,提示
-bash: python: 未找到命令
-bash: python3: 未找到命令
于是我们需要在 MSYS2 中添加软件包,请出 pacman,它移植于著名 LFS ———— Arch Linux 发行版
首先,安装一些依赖和编译工具
pacman --needed -Sy bash pacman pacman-mirrors msys2-runtime
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-gdb mingw-w64-x86_64-make tmux zsh git mingw64/mingw-w64-x86_64-cmake winpty
pacman -S mingw-w64-x86_64-python3-bsddb3 mingw-w64-x86_64-gexiv2 mingw-w64-x86_64-ghostscript mingw-w64-x86_64-python3-cairo mingw-w64-x86_64-python3-gobject mingw-w64-x86_64-python3-icu mingw-w64-x86_64-iso-codes mingw-w64-x86_64-hunspell mingw-w64-x86_64-hunspell-en mingw-w64-x86_64-enchant
接下来安装 python3 和 pip3
pacman -S mingw-w64-x86_64-python3
pacman -S python3-pip
此时 python3 和 pip3 已经安装,顺便把 pip3 升个级,最近它的版本号也像 Chrome 一样一发不可收拾。
pip3 install --upgrade pip
MSYS2 安装 vibora
再安装 vibora
pip3 install vibora
提示错误:
Running setup.py install for vibora ... error
Complete output from command /usr/bin/python3 -u -c "import setuptools, toke
nize;__file__='/tmp/pip-install-rawskw89/vibora/setup.py';f=getattr(tokenize, 'o
pen', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile
(code, __file__, 'exec'))" install --record /tmp/pip-record-9rnpdvhe/install-rec
ord.txt --single-version-externally-managed --compile:
...
unable to execute 'x86_64-pc-msys-gcc': No such file or directory
error: command 'x86_64-pc-msys-gcc' failed with exit status 1
...
Command "/usr/bin/python3 -u -c "import setuptools, tokenize;__file__='/tmp/pip-
install-rawskw89/vibora/setup.py';f=getattr(tokenize, 'open', open)(__file__);co
de=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec')
)" install --record /tmp/pip-record-9rnpdvhe/install-record.txt --single-version
-externally-managed --compile" failed with error code 1 in /tmp/pip-install-raws
kw89/vibora/
想来原因是 Vibora 依赖本地二进制程序进行异步通信。
再安装 x86_64-pc-msys-gcc
pacman -S gcc
之后,再次运行 pip3 install vibora,提示
In file included from vibora/parsers/parser.c:4:0:
/usr/include/python3.6m/Python.h:39:10: 致命错误:crypt.h:No such file or d
irectory
#include <crypt.h>
^~~~~~~~~
编译中断。
error: command 'x86_64-pc-msys-gcc' failed with exit status 1
----------------------------------------
Command "/usr/bin/python3 -u -c "import setuptools, tokenize;__file__='/tmp/pip-install-t22lx1u7/vibora/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-record-f8i8_k06/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-install-t22lx1u7/vibora/
StackOverflow 大法好,提示缺少的 头文件 crypt.h 在 libcrypt-devel 包中,于是再安装 x86_64-pc-msys-gcc
pacman -S libcrypt-devel
第三次运行 pip3 install vibora
$ pip3 install vibora
Collecting vibora
Using cached https://files.pythonhosted.org/packages/1c/db/c42998b106b89d67ce0 fe256320454ca224e4d3d05f56dd518514a5b738c/vibora-0.0.6.tar.gz
Requirement already satisfied: pendulum in /usr/lib/python3.6/site-packages (from vibora) (2.0.3)
Requirement already satisfied: python-dateutil<3.0,>=2.6 in /usr/lib/python3.6/site-packages (from pendulum->vibora) (2.7.3)
Requirement already satisfied: pytzdata>=2018.3 in /usr/lib/python3.6/site-packages (from pendulum->vibora) (2018.5)
Requirement already satisfied: six>=1.5 in /usr/lib/python3.6/site-packages (from python-dateutil<3.0,>=2.6->pendulum->vibora) (1.10.0)
Installing collected packages: vibora
Running setup.py install for vibora ... done
Successfully installed vibora-0.0.6
我的天,成功了!于是试了试官方 hello-world.py
运行 vibora hello world
from vibora import Vibora, Request
from vibora.responses import JsonResponse
app = Vibora()
@app.route('/')
async def home(request: Request):
return JsonResponse({'hello': 'world'})
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=8000)
提示:
xxx@yyyy MSYS /d/code/vibora
$ python hello-world.py
Traceback (most recent call last):
File "hello-world.py", line 1, in <module>
from vibora import Vibora, Request
File "/usr/lib/python3.6/site-packages/vibora/__init__.py", line 7, in <module>
from .server import *
File "/usr/lib/python3.6/site-packages/vibora/server.py", line 11, in <module>
from .workers.handler import RequestHandler
File "/usr/lib/python3.6/site-packages/vibora/workers/handler.py", line 3, in <module>
from socket import IPPROTO_TCP, TCP_NODELAY, SO_REUSEADDR, SOL_SOCKET, SO_REUSEPORT, socket
ImportError: cannot import name 'SO_REUSEPORT'
google 错误提示,居然来到了 vibora-issues-106,状态是关闭的,作者 @frnkvieira 说 @zzeric 已经修复,他已合入最新版,下面又有人要求打开这个 issues,说经过测试依然存在。
@zzeric_ 的解决办法是升级到 python 3.7.0,我个人认为这并非一个好的办法。 @danieldaeschle_ 的解决办法是 vibora-pull-157 ,不过作者并未接受。
我暂时采用了 danieldaeschle 的方法修改,再次运行,提示:
OSError: [Errno 112] Address already in use
不过,此时浏览器打开 http://localhost:8000 已经可以正常显示:
{'hello': 'world'}
本文的第三部分,剩下的就是作个总结。
Windows 下用 Linux 的途径
- 虚拟机
- 虚拟机是在物理宿主机上虚拟一台机器,再将 Linux 安装进去。Windows 平台的虚拟机软件也有不少选择,而且微软也内置了一种虚拟机 Hyper-V
- 类Linux / POSIX API 方案
- 这类方案是在 Windows 核心上实现一种 类Linux / POSIX 标准的中间翻译层,要么对接到 Windows 原生动态链接库,要么对接到自带的库。
- Windows Subsystem for Linux
- 这是基于市场博弈和市场的发展,微软官方基于 Hyper-V 给出了一个解决方案,这个方案可以从微软商店中下载 Linux,目前官方支持 5 种比较常见的发行版。
下面是我的一些理解
VirtualBox
在普通需求上,这是我最愿意使用的一种便携方案,比如国内银行的 usb key 只支持 Windows 时,使用虚拟机也是挺好的,适合个人。
VMWare
他们具备成熟的生产环境商业方案,但其实更适合开发环境和测试环境构建一套安全、灵活、可扩展的系统环境。但现在虚拟化的趋势中有所过气,XEN 算是 Linux 上对标的方案。但他们家显卡驱动实在不行。
Hyper-V
在虚拟微软自家系统旧版本时,这个是最佳方案,一些微软自家新技术,也是以此虚拟机发布的。
Docker
它不是虚拟机,但是目前很不错的容器虚拟化技术,但它需要 Widnows Pro 版本以上,且不能与 VirtualBox 和 VMWare 及一些 Android 模拟器共存。
Cygwin & MinGW
Cygwin 通过动态链接库 cygwin1.dll,提供一个 POSIX API 子集,编译出 Linux 下的程序通过这个库对接 Windows 底层动态链接库。
MinGW 是 GCC 在 Windows 的实现,通过编译器,把诸如 Linux 系统调用 如 fork 翻译成 Windows API 如 CreateProcess 这样。这种没有引入运行时的中间层,会比 Cygwin 更紧凑。
通俗的说 Cygwin 属于运行时适配,MinGW 属于编译时转化,从技术纯粹来说,我更喜欢 MinGW,但对于绝大多数小的程序,Cygwin 虽然多了中间层,但可移植性比 MinGW 强。
跨平台属于商业鸿沟,技术上也是一个复杂问题,之所以跨平台这个问题这么难,是因为平台差异导致的,比如可执行文件格式差异,Windows 是 PE 文件,Linux 是 ELF 文件,于是需要分别编译。
MSYS & MSYS2
MSYS 这个项目,由多年前的 MinGW 团队开始,并成为 Cygwin 的一个分支,一个从来没有跟上 Cygwin 发展的分支,目前已不活跃,如果有选择,请选择 MSYS2。
MSYS2 是 MSYS 的一个升级版,它集成了 pacman 和 Mingw-w64 的 Cygwin 升级版, 提供了 Bash 等 Linux 环境、版本控制软件(Git/hg)和 MinGW-w64 工具链。 它是由 mingw-builds 团队(也是MinGW-w64工具链的官方包装商)的 Alexey Pavlov 开发的一个项目,密切更新到最新的 Cygwin,使其不会过时。
MSYS2 不完全是基于 MinGW 的,至少其原生工具都是链接到自带的一套特定版本的 Cygwin DLL ,基本上只是用 libalpm 管理 MSYS2、MinGW-w64 和 MinGW 三个不同子系统的软件包。 Cygwin、MSYS 和 Git for Windows(前称 msysgit)里各有一套 Cygwin DLL 而且互不兼容,而 MinGW 那两个子系统都不需要链接到任何版本的 Cygwin DLL。
Windows Subsystem for Linux
下载安装都很容易,可以在 Windows Store 下载,其中的坑在评论中都已解决。
- 用户可以使用 Linux 常见工具:grep, sed, awk, Bash, vim, emacs, tmux 等
- 可以支持很多运行时:Javascript/node.js, Ruby, Python, C/C++, C# & F#, Rust, Go
- 以及很多 Linux 的服务端软件:sshd, MySQL, Apache, lighttpd
- 还可以使用包管理器,如 apt-get 等
- 支持 Linux 和 Windows 程序的双向调用
我有安装过 WSL Ubuntu,其性能不高,图形包等并未尝试,相比虚拟机,觉得目前不具太大意义。
总结
总的来说,本文讲了 Windows 下用 Linux 的两个例子,再总结了一些 Windows 下 使用 Linux 的方法,整体内容很多。
最后来说,一个更好的方案可能是一台高配 macOS 运行 Parallels Desktop,再其中运行 Windows ;)
感谢阅读。