在Windows下使用共享的Node.js安装的Linux子系统(WSL):Node.js npm和npx二进制文件无法工作

6

我最近转到了Windows + WSL环境(顺便说一下,WSL非常好用)。这么做的主要原因是为了有个Linux开发环境,同时在Windows上运行其他应用程序和游戏,而无需重新启动计算机(之前是双启动设置)。

在安装过程中,我发现大多数已安装的Windows二进制文件可以从WSL执行。因此,我可以通过在Windows中安装java和maven来避免重复安装,以便使用Eclipse IDE,并将其链接到WSL,以便在终端中使用它们。

但是使用相同的方式安装node后,发现node npm和npx二进制文件无法工作 :(

我想要一个单独的node安装,我可以使用nvm windows进行管理。因此,我以下面的方式开始安装:

在WSL中,我配置了/etc/wsl.conf,按照Nick Janetakis的指南(感谢Nick),以使Windows驱动器挂载在/而不是/mnt/下:

/etc/wsl.conf

[automount]
root = /
options = "metadata"

然后在Windows中安装了Node:
C:\Windows\system32> nvm install 10.15.0
... installing process...
C:\Windows\system32> nvm use 10.15.0
...success message...
C:\Windows\system32> node -v
v10.15.0
C:\Windows\system32> npm -v
6.4.1

到目前为止,一切都按预期进行。下一步是将Windows节点二进制文件链接到WSL。这些二进制文件位于以下位置:

C:\Windows\system32> where node
C:\Program Files\nodejs\node.exe

C:\Windows\system32> where npm
C:\Program Files\nodejs\npm
C:\Program Files\nodejs\npm.cmd

C:\Windows\system32>where npx
C:\Program Files\nodejs\npx
C:\Program Files\nodejs\npx.cmd

所以在WSL终端中(记住我的磁盘挂载在/c而不是默认的/mnt/c):

user@host:~$ mkdir ~/bin
user@host:~$ ln -s /c/Program\ Files/nodejs/node.exe ~/bin/node
user@host:~$ ln -s /c/Program\ Files/nodejs/npm ~/bin/npm
user@host:~$ ln -s /c/Program\ Files/nodejs/npx ~/bin/npx

并且...

user@host:/d/tmp$ node -v
v10.15.0
user@host:/d/tmp$ echo "console.log('Hello World');" >> index.js
user@host:/d/tmp$ node index.js
Hello World

太好了!(注意:由于Node已安装在Windows上,因此在WSL上使用时必须将其用于磁盘驱动器中,本例中为/d)。但是...

user@host:~$ npm -v
internal/modules/cjs/loader.js:583
throw err;
^

Error: Cannot find module 'C:\home\user\bin\node_modules\npm\bin\npm-cli.js'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:581:15)
at Function.Module._load (internal/modules/cjs/loader.js:507:25)
at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)
at startup (internal/bootstrap/node.js:283:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:743:3)

这就是我写下这封邮件的原因。错误很明显,npm试图在一个混乱的路径中找到npm-cli.js,其中包含了Windows路径中npm符号链接的位置。

有没有办法告诉npm/npx正确的Windows路径,让它从WSL中找到文件?

很抱歉问题比较长,但由于设置非常特殊,所以我认为这种情况的背景必要。


我的回答或者其他人的回答解决了你的问题吗? - Ben Smith
5个回答

2

我无法在Windows 10中使用Ubuntu 20.04 LTS的WSL安装npm。

然而,当我按照这里的说明操作时,我成功地让它工作了。请注意,它说它是针对WSL2的,但在WSL1环境中安装node的步骤也是有效的(截至7月20日,我仍然无法在我的Windows 10版本中获得WSL,真是烦人!)。

简而言之,这个解决方案让您在WSL环境中安装nvm(node版本管理器)。

sudo apt-get install curl
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash

您可以安装一个新版本的node,它默认包含npm,例如:
nvm install --lts

Ben,你按照这个过程操作后,npx 能用了吗?我在 Ubuntu 上使用类似的方法安装 nvm 和 node,与我在 Windows 上安装的 nvm 和 node 分开。问题是,在 Ubuntu 终端中运行 'which npx' 仍然会响应 "/mnt/c/Program Files/nodejs/npx"。尝试在 Ubuntu 中运行 npx 会导致错误 "/mnt/c/Program Files/nodejs/npx: bin/sh^M: bad intrepreter: No such file or directory"。但是,在 Ubuntu 中运行 'which node' 响应为 "/usr/bin/node",并且当我执行 node 命令时一切似乎都正常。 - Lazor
1
嗨@Lazor。当我按照这些步骤操作时,我成功地让nvm(和node)工作了,尽管我不认为我试过npx。然而,当我在WSL中进行这项工作时,我发现WSL是将Windows路径添加到Linux路径的罪魁祸首。幸运的是,WSL有一种方法可以阻止这种行为,就像我在这里发布的那样。希望这能帮到你! - Ben Smith
1
嗨Ben,感谢你的帮助。老实说,我不记得发生了什么变化,但我在Windows 10上进行了Ubuntu的全新安装,一切都正常工作了。在安装nvm和最新版本的Node JS之后,npm和npx都可以正常使用。 - Lazor
1
太好了,@Lazor。我曾经遇到过类似的问题,所以我知道你的感受(以及当你解决问题时的如释重负!) - Ben Smith

1

对现有答案进行整合和扩展...

首先,主要答案如下:

  • 不要在WSL/Linux中尝试使用Windows版本的NodeJS。

    原因有几个:

    1. Windows版的NodeJS工具链将期望(a)使用Windows路径而不是Linux路径(这是此问题中出现的问题)

    2. 即使你解决了这个问题(这就像在风车上倾斜),正如@AnselmoPark在这个答案的评论中指出的那样:

      一些node模块在[Windows]和WSL上有不同的实现

      还可以参见这个问题及其答案以获取更多信息。

  • 相反,在WSL中安装并使用NodeJS工具链的Linux版本。

    这就是BenSmith的答案最终想表达的,但我想补充说,您可以在Linux发行版中使用任何受支持的NodeJS安装方法。例如,在Ubuntu上,您可以从仓库安装(但请确保您的发行版具有受支持的版本或从PPA安装)。

    个人而言,我使用n,但是再次强调,您可以选择最舒适的任何方法。重要的是,在WSL2 Linux分发中安装Linux版本。

尚未在任何答案中涵盖的次要信息(但在评论中作为“仍然无法工作”出现)-- 如果您已同时安装了Windows版本和Linux版本(在WSL中),则可能会像@Lazor在此答案的评论中那样陷入困境。

问题发生的原因是Windows Node为那些运行Git Bash的用户提供npm作为shell脚本。但是,此脚本仍指向Windows工具的版本。

如果Windows NodeJS出现在路径中的Linux版本之前,则(当然)它将优先使用。你需要:

  • 确保Linux版本排在第一位
  • 或删除Windows版本。

请不要遵循建议(如此答案)完全从WSL中删除所有Windows路径,因为这将严重限制您在WSL中运行Windows应用程序的能力(这是其伟大功能之一)。

相反,通常使用Linux的nvm(或n或其他工具)就足以将Linux NodeJS目录置于首位


1
有什么解决方法吗?我遇到了相同的情况,希望在WSL终端和Windows中同时运行相同的node和npm,因为我想在终端(WSL)和IDEA(Windows)中运行它们。
我发现npm不能通过驱动器运行,比如在C:/下使用已经安装在F:/下的npm,会导致错误:
internal/modules/cjs/loader.js:638
    throw err;
    ^

Error: Cannot find module 'C:\f\Users\aleen\AppData\Roaming\nvm\v10.21.0\node_modules\npm\bin\npm-cli.js'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15)
    at Function.Module._load (internal/modules/cjs/loader.js:562:25)
    at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)
    at startup (internal/bootstrap/node.js:283:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3)

然而,我们总是在一个驱动器中工作,这意味着我们可以在常用的驱动器下安装npm(对我来说是F:/),并通过相对路径为其创建别名,在该驱动器内运行。
# ~/.bash_aliases
function npm() {
  $(realpath --relative-to="$(pwd)" /mnt/f/Program\ Files/nodejs)/npm $@
}
export -f npm

该问题已经创建,以告知Node:https://github.com/nodejs/node/issues/34165 - PuiMan Cheui

0
我所做的是修改位于C:\Program Files\nodejs的npm bash文件。
替换为:
"$NODE_EXE" "$NPM_CLI_JS" "$@"

使用这个:

"$NODE_EXE" "/Program Files/nodejs/node_modules/npm/bin/npm-cli.js" "$@"

然后将其保存为 WSL 内部的 Unix 格式文件。


0

我有自己的开发环境,所以无法在您的环境中进行测试。 但是,我建议您检查一下在WSL上“Program Files”下的npm是否正常工作。

user@host:~$ /c/Program\ Files/nodejs/npm -v

在我的情况下,运行上述命令时会出现另一个错误。
Error: EINVAL: invalid argument, uv_pipe_open

如果您的环境也是这样的话,您可以先解决这个问题。

关于模块路径问题,似乎是由路径引起的;原始的npm(在Program Files下)和您的符号链接具有不同的当前路径。

我对原始的npm进行了以下修改:

#!/bin/sh
(set -o igncr) 2>/dev/null && set -o igncr; # cygwin encoding fix

basedir=`dirname "$0"`

echo $basedir  # Added code

case `uname` in
    *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
esac
...

如果您运行原始的npm和您的符号链接,$basedir将显示不同的结果,这会导致模块路径问题。

如果您可以解决第一个问题(uv_pipe_open错误),那么考虑将nodejs目录添加到您的路径中,而不是使用符号链接如何?


我建议您检查一下简单的网络node.js程序是否正常工作。我怀疑Windows版本的node.exe对套接字有不同的实现。 - Anselmo Park
我没有遇到无效参数错误,您使用了什么设置? 使用原始位置的二进制文件会导致相同的行为,但路径不同(WSL内部的Windows路径)。找不到模块“C:\ c \ Program Files \ nodejs \ node_modules \ npm \ bin \ npm-cli.js”这里似乎有两件事情正在发生。 npm脚本无法获取符号链接的规范路径,并且在具有正确路径的情况下,它需要转换为Windows路径:/ c / foo / bar / baz> c:/ foo / bar / baz。 我将尝试修改npm脚本以实现此目的。也许这可以成为对节点源的PR? - Sebastiandg7
我在WSL上使用nvm,在Git Bash上使用nvm-windows - Anselmo Park
1
据我所知,Node.js 对于 Windows 来说并不完全兼容 WSL。一些 Node 模块在 Git Bash 和 WSL 上的实现也有所不同。因此,我在 WSL 和 Git Bash 上独立设置了 Node.js。 - Anselmo Park

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接