在两年前的八月
在 Windows 上原生运行 Linux 可执行文件
然而 Bug10 也不是浪得虚名
经过了两年的发展
1. 我理想中的命令行界面
既然违反广告法取了这么个标题
- 好看
配色( 字体可以自由设定、 ) ; - 支持 UTF-8 字符的输入与显示
; - 支持常见的 *NIX 命令行工具
cat( grep、 awk 等、 ) ; - 自动补全
语法高亮、 历史记录、 ; - 完善的复制粘贴支持
; - 互操作性
共享文件系统( 网络栈、 可调用 Win32 程序, ) ; - 支持常用的脚本语言
PHP( Python、 Node.js 等、 ) ; - 包管理器
以及其他各种常用软件的支持, ; - 快速呼出
快捷键( 右键菜单入口、 ) 。
然而遗憾的是
2. 难用的 Windows 命令行
停停停
首先我要对标题做出一些订正
但是grep
对应 PowerShell 中的 Select-String
uniq
对应 Select-Object -Unique
等
▲ 图片来源
当然
回到正题
虽然 Windows 的命令行一直遭人诟病
然而
带着他新鲜出炉的 WSL
3. Windows Subsystem for Linux, 参上!
大家都把 WSL 吹得这么牛逼
简单来说
首先
了解过一点操作系统原理的同学应该都知道ls
命令dir
命令
当我们在 Linux 上执行 ls
命令ls
会调用 getdents
这个系统调用dir
命令dir
会调用 NtQueryDirectoryFile
这个 API
然而ls
会尝试调用 getdents
系统调用ls
也想
但是有了 WSL
依然拿 ls
举例ls
命令时ls
会调用 getdents
系统调用NtQueryDirectoryFile
ls
也就是说
只要实现了足够多的系统调用翻译
相信各位都听说过鼎鼎大名的 Cygwin
虽然 Cygwin 提供了完整的 POSIX 系统调用 APICygwin*.dll
的形式提供lxcore.sys
与 lxss.sys
处理
同样是将 POSIX 系统调用转换为 Windows 中的 APIfork
fork
等系统调用
▲ WSL 架构示意图
最重要的一点Cygwin*.dll
Cygwin1.dll
而在 WSL 下
▲ Cygwin 目录下
最后总结一波
WSL 就像是一个翻译官
而那些使用了 Cygwin 重新编译后的 Linux 应用程序
但是每次添加新程序都要改造
以上只是我对 WSL 的粗浅解释
4. 安装 WSL, 拥抱可爱的 Linux
好了不说废话
第一步
如果你懒得用 GUI
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
第二步
第三步
至此
你也可以同时安装多个发行版
5. 使用更专业的终端模拟器
我猜你现在正在对上面那个窗口发呆
如果你正在使用中文 Windows 系统
好吧不开玩笑
因此
终端模拟器是什么
为了这个回答这个问题 ? 我专门写了一篇文章 , 去看看吧 , :P 。
我个人比较推荐的终端模拟器有
-
专门为 WSL 开发的终端模拟器
基于 mintty 与 wslbridge, 稳定易用, 。 -
Windows 上的老牌终端模拟器
功能极为强大, 要啥有啥, 。 -
基于 Electron 的跨平台终端模拟器
好看和可扩展性是卖点, BUG 不少, 。
还有其他各种各样的终端模拟器
另外
▲ 我正在使用的终端好看是第一生产力
6. 让我们更深入一些
以下是 WSL 的一些优化技巧
6.1 使用软件源镜像
由于众所周知的原因
我目前使用的是 清华大学的 Ubuntu 镜像源
6.2 安装 zsh 与 oh-my-zsh
想要快乐地使用命令行
我个人习惯使用 zsh
# ~/.oh-my-zsh/custom/themes/robbyrussell-ascii.zsh-theme
# Modified from robbyrussell, the default theme of oh-my-zsh.
# > blog git:(source) x $
local ret_status="%(?:%{$fg_bold[green]%}>:%{$fg_bold[red]%}>%s)"
PROMPT='${ret_status} %{$fg[cyan]%}%c%{$reset_color%} $(git_prompt_info)$ '
ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg_bold[blue]%}git:(%{$fg[red]%}"
ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%} "
ZSH_THEME_GIT_PROMPT_DIRTY="%{$fg[blue]%}) %{$fg[yellow]%}x%{$reset_color%}"
ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg[blue]%})"
# ~/.zshrc
ZSH_THEME="robbyrussell-ascii"
plugins=(git zsh-completions zsh-autosuggestions zsh-syntax-highlighting)
6.3 安装多个发行版
Windows 10 Fall Creators Update 之后wslconfig.exe
来查询已安装的发行版
删除发行版也很简单
6.4 多种进入 WSL 的方式比较
新版支持同时安装多个发行版bash.exe
入口了
秋季创意者更新之后的 Windows 提供了 多种进入 WSL 环境的方式
wsl.exe
打开默认发行版中的默认 Shell
。 <distroname>.exe
打开指定发行版中的默认 Shell
。 bash.exe
(DEPRECATED)打开默认发行版中的 bash Shell
。 如果你更改了默认 Shell 却总是打开 bash
就说明你使用了这个入口, 。
你也可以通过这些入口直接在 WSL 中执行命令并返回结果
<distroname> -c [command]
bash -c [command]
wsl [command]
不再需要指定( -c
)
6.5 与 Windows 的互操作性
WSL 与 Windows 之间的互操作性 (Interoperability) 很牛逼
Windows 下的所有盘符都挂载在 WSL 中的 /mnt
目录下C:\Users\{你的用户名}\AppData\Local\Packages\{Linux发行版包名}\LocalState\rootfs
目录中
$ ls /mnt
c d e
$ mount -l
rootfs on / type lxfs (rw,noatime)
C: on /mnt/c type drvfs (rw,noatime,uid=1000,gid=1000)
D: on /mnt/d type drvfs (rw,noatime,uid=1000,gid=1000)
E: on /mnt/e type drvfs (rw,noatime,uid=1000,gid=1000)
你可以在 Windows 命令行环境中直接调用 WSL 中的命令
PS C:\temp> wsl ls -al
total 0
drwxrwxrwx 1 prin prin 4096 Sep 7 19:04 .
drwxrwxrwx 1 prin prin 4096 Sep 7 18:38 ..
-rwxrwxrwx 1 prin prin 4 Sep 7 19:04 foo.txt
你也可以在 WSL 中调用 Windows 中的命令行程序
$ which ipconfig.exe
/mnt/c/Windows/System32/ipconfig.exe
$ ipconfig.exe
Windows IP Configuration
...
你可以在 WSL 中直接启动 Windows 应用
$ notepad.exe "C:\temp\foo.txt"
你还可以通过 pipes 与 Windows 程序通信
# 复制内容至 Windows 剪贴板
$ cat foo.txt | clip.exe
你甚至可以把 Windows 命令和 WSL 命令混着用
PS> ipconfig | wsl grep IPv4
IPv4 Address. . . . . . . . . . . : 192.168.1.114
$ ipconfig.exe | grep IPv4 | cut -d: -f2
192.168.1.114
$ ls -al | findstr.exe foo.txt
-rwxrwxrwx 1 prin prin 4 Sep 7 19:04 foo.txt
$ cmd.exe /c dir
Volume in drive C is Windows
Volume Serial Number is B263-****
Directory of C:\temp
2018/09/07 19:04 <DIR> .
2018/09/07 19:04 <DIR> ..
2018/09/07 19:04 4 foo.txt
1 File(s) 4 bytes
2 Dir(s) 194,422,341,632 bytes free
同时
- 在 WSL 中启动 web server
在 Windows 上使用浏览器访问, ; - 在 Windows 下启动 MySQL/Redis 服务器
在 WSL 中连接, ; - 诸如此类
。
如果你对 WSL 与 Windows 之间互操作的原理有兴趣
6.6 DrvFs 文件权限问题
虽然 WSL 中可以直接访问 Windows 磁盘的内容ls
不会感到陌生0777
了呢
这主要是 DrvFs 中 Linux 文件权限的实现导致的
在 WSL 中
VolFs
着力于在 Windows 文件系统上提供完整的 Linux 文件系统特性
通过各种手段实现了对 Inodes, Directory entries、 File objects、 File descriptors、 Special file types 的支持、 比如为了支持 Windows 上没有的 Inodes。 VolFs 会把文件权限等信息保存在文件的 NTFS Extended Attributes 中, 记得我上面警告过你不要在 Windows 中修改 WSL 里的文件吗。 就是因为 Windows 中新建的文件缺少这个扩展参数? VolFs 无法正确获取该文件的 metadata, 而且有些 Windows 上的编辑器会在保存时抹掉这些附加参数, 。 WSL 中的
/
使用的就是 VolFs 文件系统。 DrvFs
着力于提供与 Windows 文件系统的互操作性
与 VolFs 不同。 为了提供最大的互操作性, DrvFs 不会在文件的 NTFS Extended Attributes 中储存附加信息, 而是从 Windows 的文件权限, Access Control Lists( 就是你右键文件 > 属性 > 安全选项卡中的那些权限配置, 推断出该文件对应的的 Linux 文件权限) 。 所有 Windows 盘符挂载至 WSL 下的
/mnt
时都是使用的 DrvFs 文件系统。
由于 DrvFs 的文件权限继承机制很微妙0777
ls
干瞪眼
要启用 DrvFs 的 metadata 支持
# 修改成你自己的盘符
$ sudo umount /mnt/e
$ sudo mount -t drvfs E: /mnt/e -o metadata
不过如果仅仅是执行了这个0777
chmod
一遍
$ sudo mount -t drvfs E: /mnt/e -o metadata,uid=1000,gid=1000,umask=22,fmask=111
这样磁盘下的文件的默认权限就是 0644
ls
也不会再是绿油油一片啦
不过每次使用时都要重新挂载未免也太烦/etc/wsl.conf
[automount]
enabled = true
root = /mnt/
options = "metadata,umask=22,fmask=111"
mountFsTab = true
# 这个文件里还可以添加其他配置项,有兴趣的可以看看上面的链接
重启终端mount -l
查看
另外chmod +x
一下C:
排除掉/etc/fstab
wsl.conf
中的 mountFsTab
为 true
/etc/fstab
# 不在此列表中的盘符会使用 wsl.conf 中的参数挂载
# 格式可以自己去查 fstab 的帮助文档
E: /mnt/e drvfs rw,relatime,uid=1000,gid=1000,metadata,umask=22,fmask=111 0 0
6.7 其他关于 WSL 的折腾
虽然 Microsoft 开发 WSL 出来主要是着重于命令行环境的使用
也有人试过在 WSL 中运行完整的 DE
另外
如果你对 WSL 的底层实现有兴趣
- https://blogs.msdn.microsoft.com/wsl/
- https://blogs.msdn.microsoft.com/commandline/tag/wsl/
7. 总结
虽然 WSL 很不错
对我来说
如果你和我的需求一样
而且最近几年 Microsoft 在笼络开发者方面的努力大家有目共睹
Microsoft