WSL

记一次诡异的被 yarn 坑的过程

事情的起源是 @tdzl2003 说他用 VSCode 的 remote 模式用的很开心,放弃 Hyper-V 回到 VirtualBox 的怀抱,笨狗去看了下 remote 相关功能好像还在 VSCode Insider 里,可以装来试试看,弄好后看了下文档和教程,知道插件分装在本地和装在远端,但是项目里 eslint 插件就一直在报错,说找不到模块

找不到就去补吧,到远端的目录下 yarn install 装好依赖,回到本地一看,还是报错,怎么会这样?在远端也执行下看看?

$ ./node_modules/.bin/eslint index.js
Error: Cannot find module 'jsx-ast-utils/elementType'
...

What the fuck?! 一定是哪里不对,把 jsx-ast-utils 这个包也重装一下?再来

$ yarn add jsx-ast-utils
$ ./node_modules/.bin/eslint index.js
Error: Cannot find module 'jsx-ast-utils/elementType'
...

你特么是在逗我?去看看这个包到底怎么回事,里面只有 lib src 两个目录,其他都没有,看起来好像是不太对

确认了一下环境,Windows 10 Pro 1903, WSL Ubuntu 18.04.2, node 12.3.1, yarn 1.16.0,都是最新的,换个环境试试看?在自己另一台 MacBook Pro 上 yarn install 后就是正常的,hmmm,难道是 Windows 目录挂载到 WSL 下后文件权限啥的锅?试了下在 WSL 里用 WSL 的文件系统重新来过,问题依旧。在 Windows 里把 WSL 映射成网络盘,用 PowerShell 进到 WSL 文件系统里 yarn install 就是好的,嗯?好了?回到 WSL 下执行 PowerShell 安装好的 node_modules 也成功

难道是 WSL 的奇怪问题,搜了下好像也没有任何相关信息?难道是最近新崩的问题所以大家都找不到,我印象中之前确实也能跑来着?那就是这个锅了。等几乎认定就是 WSL 有奇怪的问题后,晚上回家后拿另一台同样环境的机器,在 WSL 下就正常的装好了

这这这,等会,冷静一下,一定有哪里不对,要不用下重启大法?把所有相关的东西都干掉重来一下?在有问题的机器上,把 git 仓库清空重来(虽然之前已经换不同的路径做过了),把 nodejs 和 yarn 都卸载重装,对了是不是跟 yarn 源还有关系?确认一下

$ yarn config get registry
https://registry.yarnpkg.com

果然这里不一样,忘了改成淘宝源,改一个再来一次(官方源为啥可能会有坑嘛,难道是最近撞墙撞的?不管了先死马当活马医好了)

$ yarn config set registry https://registry.npm.taobao.org
yarn config v1.16.0
success Set "registry" to "https://registry.npm.taobao.org".
Done in 0.06s.

这下应该没问题了,走你,等 yarn install 跑完,先检查下 node_modules/jsx-ast/utils/ 路径下文件对不对,嗯?还是只有 lib src 这两个文件夹?这到底是为什么啊,yarn 你这个坑货,要不换 npm 试试看?

npm install 跑一下,提示有文件权限不对,看了下,哦是之前有 sudo npm install -g 装过东西,把 ~/.npm 目录下相关内容清掉就好了。用 npm 装完一看,好了。。。呃,果然 yarn 你个坑货到底哪里不对啊!?

缓存?去吧 ~/.yarn 下的内容都清掉,/tmp 下有一堆 yarn- 开头的不知道是啥应该也都可以干掉,再来,还挂?去搜 yarn install package missing files,终于看到了一个很相似的情况,不过他这个最后也是清了 yarn 的 cache 就好了。看了下除了 ~/.yarn 还有人说 Cache 目录是 ~/.yarn-cache 目录,但是我压根都没这个目录啊。顺着这条线索继续搜,找到 yarn cache clean 这个命令,执行后再装就好了

那看来就是之前的缓存有问题,而我弄这么多各种重装也并没有清掉 cache,或者触发重新从远端拉包。那么 yarn 的 cache 到底在哪里?到用户根目录下查看所有文件,发现有一个目录叫 .cache,看着挺可疑,进去看看果然里面有 pipyarn 等目录,看了下里面文件时间,就是这了,应该就是之前某次安装过程中被强制退出,导致那个点在装的一个或几个包是不对的,但是目录还在 yarn 就一直傻乎乎的用本地的

结论:yarn 的 cache 机制对包的完整性保证不够,如果之前安装过程中有异常退出,赶上异常退出过程中的包就有可能损坏,后面如果不手动清 cache,就会一直挂

cmder 在 Win10 WSL 下粘贴丢字符的解决

Win10 升级到 1803 后,用 cmder 连的 bash,粘贴文本时总丢大量字符,怀疑某些部分被识别成了控制字符或怎样。一开始以为是 WSL 的问题,不过后面交叉验证,发现如果用 cmder 开 Windows 命令行,或直接在 Windows 命令行下运行 bash 就没事。翻了好久,终于在 ConEmu 项目下找到相关讨论,作者最近认可了这个问题并发布了更新:https://github.com/Maximus5/ConEmu/issues/1545#issuecomment-386444227

因为 cmder 就是封装了一下 ConEmu,所以去 https://github.com/Maximus5/ConEmu/releases/tag/v18.05.06 下载最新的 180506 版本 ConEmu,并解压到 cmder 目录的 cmder\vendor\conemu-maximus5 下替换原来的文件就好

WSL 下一些奇怪的路径依赖问题优化

在公司换用 Windows 做开发机,装了 Windows Subsystem for Linux(WSL),也就是那个 Ubuntu,用来跑开发环境

我的代码放在 Windows 的文件系统里,在 WSL 里通过 ln -s /mnt/c/foo ~/foo 的方式映射过去,不过在跑 yarn 装 node modules 的时候,会经常出现路径依赖的错误,大概就是 /mnt/c/xxxxx 这样的路径在计算父目录或子目录时会出问题

另外我跑 Docker,是使用 Docker for Windows 作为宿主,在 WSL 里装 Linux 的 Docker 客户端做控制,跑 docker-compose 总是发现挂载不上开发目录到文件系统,最后看了下是 WSL 默认的 /mnt/c/ 这样的挂载点识别有问题

最后按某些野路子方法,把 WSL 访问宿主机的入口调整为 /c/ 这样就好了

$ sudo mkdir /c
$ sudo mount --bind /mnt/c /c

不过这有个问题是重启后需要重新挂载,之前有按别的一些处理方式写到 /etc/fstab 文件表里,但是 WSL 不支持自动加载,所以按 https://nickjanetakis.com/blog/setting-up-docker-for-windows-and-wsl-to-work-flawlessly 的提示来加到 ~/.bashrc 里或我的 ~/.zshrc 里,并把 /bin/mount 改成所有用户都可启用

$ echo "sudo mount --bind /mnt/c /c" >> ~/.bashrc && source ~/.bashrc
$ sudo echo "yourname ALL=(root) NOPASSWD: /bin/mount" >> /etc/sudoers

注 1:yarn 的问题似乎现在在 /mnt/c/foo 这样的目录结构下工作正常了,不确定是不是 yarn 升级处理了这个问题