Windows 系统的 cmd 工具饱受开发人员的非议,后来 Windows 内置了 Linux 子系统 WSL (Windows subsystem for Linux),并推出了 Windows Terminal 工具,其中可打开 Ubuntu bash 终端,并且可访问 Windows 系统的文件,虽然我以前已经习惯了使用 Cmder 终端提供的 bash,但还是想试试 WSL。 但是在使用时发现,在这个 bash 终端中使用 node/npm/npx 命令会出现错误,无法使用。搜索发现不少人遇到这个问题,在 microsoft/WSL 的仓库中提了 issue。查看下来发现多数人的解决方法是在子系统中重新安装 node,但我不想把同一样工具安装两个,之后终于找到了解决方法,并在这里记录下整个过程。
在 Windows 的 WSL 终端下,运行 npm 命令提示错误
1 2 3 4
$ npm -v : not foundram Files/nodejs/npm: 3: /mnt/c/Program Files/nodejs/npm: : not foundram Files/nodejs/npm: 5: /mnt/c/Program Files/nodejs/npm: /mnt/c/Program Files/nodejs/npm: 6: /mnt/c/Program Files/nodejs/npm: Syntax error: word unexpected (expecting "in")
原因是回车符号,使用 vim -b npm 打开 npm 文件,可以看到每行后面多了个 ^M 的符号;这个符号代表的是 Windows 系统下的回车符 \r。 一般地,Unix 类系统的换行采用的是 LF,即 \n; 而 Windows 系统的换行则是 CRLF,即 \r\n; 这多出来的 \r 就是上述错误的罪魁祸首。
通过命令 dos2unix npm 把文件转换为 Unix 系的文件格式即可解决这个问题。
但是转换之后再次运行,又出现了错误:
1 2 3 4 5 6 7 8 9 10 11 12
$ npm -v module.js:472 throw err; ^
Error: Cannot find module 'C:\mnt\c\Program Files\nodejs\node_modules\npm\bin\npm-cli.js' at Function.Module._resolveFilename (module.js:470:15) at Function.Module._load (module.js:418:25) at Module.runMain (module.js:605:10) at run (bootstrap_node.js:420:7) at startup (bootstrap_node.js:139:9) at bootstrap_node.js:535:3
具体原因不清楚,猜测大概是在 Windows 系统中 /mnt/c/... 不被认为是绝对路径,然后在前面加了个盘符,结果导致路径查找错误。
最后使用 WSL issues/1512 felipemanga 提供的方法 解决了这个问题。
思路就是修改 npm 文件中的 NODE_EXE 文件路径,然后新建一个 node 文件,并在其中把路径改为 Windows 路径。
#!/bin/bash # 遍历参数 for var in"$@" do # 如果参数是一个存在的文件路径 if [ -e "$var" ] then # 修改文件路径 /mnt/c/path/to/file => c:\path\to\file var=$(echo"$var" | sed -e 's,^/mnt/\([a-z]\)/,\1:/,' | sed -e 's,/,\\,g') fi # 收集参数 Args=("${Args[@]}""$var") done
# node 文件 + # 是否在 WSL 中运行 + inWSL="$(uname -a | grep Linux | grep Microsoft)" for var in "$@" do - if [ -e "$var" ] # 仅在 WSL 中时,修改文件路径格式 + if [[ $inWSL && -e "$var" ]] then var=$(echo "$var" | sed -e 's,^/mnt/\([a-z]\)/,\1:/,' | sed -e 's,/,\\,g')