使用WSL2与安装在Windows上的应用程序进行交互

4

我已经成功运行了WSL2。在Windows上,我安装了node.js,并希望从Ubuntu层运行npm install snowflake-sdk。终端返回-bash: /mnt/c/Program Files/nodejs/npm: /bin/sh^M: bad interpreter: No such file or directory,而PowerShell正常工作。

问题是:是否可以使用WSL2的终端与在Windows上安装的应用程序进行交互?

2个回答

7

注:

  • 更典型的情况是按照官方指南在Linux侧安装Node.js和npm感谢SeaDude。如果需要从Windows调用,则可以使用 wsl npm ...,但请注意WSL2中跨文件系统调用通常不被建议

harzvor 的有用回答提供了良好的背景信息。

虽然不太明显且有些繁琐,但确实可以使从WSL2调用Windows安装的Node.js副本中的npm工作。您可以将解决方法包装在自定义函数或脚本中

# From WSL2; note the required use of '.exe'
node.exe 'c:/Program Files/nodejs/node_modules/npm/bin/npm-cli.js' install snowflake-sdk

上面的代码依赖于在Windows上安装了Node.js并且使用默认位置,间接地调用npm,使用与CLI入口点在Windows上使用的npm.cmd批处理文件基本相同的技术。
注意:
为了从WSL中针对Windows可执行文件,必须显式地包含文件扩展名,例如使用 node.exe 而不是 node
否则,在使用 npm 等命令时,Linux子系统将在 $PATH 文件夹中查找该名称的无扩展名文件,这样是行不通的。即使在Windows上实际存在这样的文件,但它是一个基于shebang的脚本,专为类Unix平台设计,实际上在Windows安装中并没有作用,但Linux子系统仍然尝试执行它,因为它使用CRLF(\r\n)换行符而不是预期的LF-only(\n)换行符。结果,跟随#!/bin/sh 之后的意外CR(在错误消息中表示为^M)被认为是可执行路径的一部分,因此调用失败。
然而,即使手动解决这个问题(转换为LF-only换行符)也无济于事,因为shell脚本构建npm-cli.js入口点的完整路径的方式,它将其表达为通过WSL文件系统瞄准Windows文件系统位置的UNC路径,如:\\wsl$\Ubuntu-20.04\mnt\c\... - 这是明确禁止的。
直接调用批处理文件npm.cmd也不起作用,无论是直接调用还是使用cmd.exe /c npm.cmd ...都不起作用:直接调用*.cmd文件会失败并且原因难以理解 - 不确定在Windows 10 20H2中是否存在此问题。使用cmd.exe /c也会失败,因为cmd.exe不支持UNC路径作为当前目录,并且WSL2内部的当前目录路径总是表达为一个(例如,\\wsl$\Ubuntu-20.04\home\jdoe\project\some-project)。在这种情况下,cmd.exe默认为Windows目录,因此无法将包安装到当前WSL目录(项目)中。
提供npm CLI的主.js文件的完整Windows本机路径给node.exe,可以按预期工作,因为Node.js似乎能够正确处理引用WSL2文件系统目录和文件的UNC路径,例如调用WSL2的shell当前目录。

[1] 在Ubuntu 20.04上,位于shebang行本身的CR字符似乎不再是问题了,但是剩余行中的CR字符仍然会导致调用失败,错误信息更加晦涩,例如:: not foundram Files/nodejs/npm: 3:

[2] 原因在于Linux的dirname工具被用于确定shell脚本所在的目录,以便确定npm-cli.js的完整路径,而这个工具的设计是从Linux文件系统的角度来操作的,它通过这种间接的、不受支持的方式表达了脚本在Windows文件系统中的位置。


2

是否可以使用WSL2终端与Windows级别安装的应用程序进行交互?

是的,您可以从WSL运行notepad.exe,它将在Windows中打开记事本。

更多文档:https://learn.microsoft.com/en-us/windows/wsl/interop#run-windows-tools-from-linux

解决NPM问题

如果我尝试在WSL中运行npm -v,会出现找不到文件的错误:

PS C:\Users\harvey> bash
harvey@harvey-w10x64-defiance:/mnt/c/Users/harvey$ npm -v
internal/modules/cjs/loader.js:968
  throw err;
  ^

Error: Cannot find module 'C:\mnt\c\Program Files\nodejs\node_modules\npm\bin\npm-cli.js'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:965:15)
    at Function.Module._load (internal/modules/cjs/loader.js:841:27)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
    at internal/main/run_main_module.js:17:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}

文件路径基本正确,但是它在末尾添加了C:\mnt

我通过向Node提供npm-cli.js文件的路径来解决这个问题,成功避开了这个问题。

你可以运行:

node.exe \c\Program Files\nodejs\node_modules\npm\bin\npm-cli.js -v

但是这会遇到相同的错误。
然后我尝试了这个:
PS C:\Users\harvey> bash
harvey@harvey-w10x64-defiance:/mnt/c/Users/harvey$ cd "/mnt/c/Program Files/nodejs/node_modules/npm/bin"
harvey@harvey-w10x64-defiance:/mnt/c/Program Files/nodejs/node_modules/npm/bin$ ../../../node.exe npm-cli.js -v
6.14.6

从这里开始,我终于能够从NPM CLI得到一些输出了。

从这里开始,我可以安装包,但它可能被安装在错误的位置。

我似乎无法从文件系统的任何地方让npm工作。这可能是NPM的限制。也许如果你尝试更改路径环境变量,你就可以让它工作?


有趣的是,我用Confluent Kafka做了同样的场景。在带有“/mnt/”前缀的目录中导航完美地运作。我可以启动我的kafka,docker-compose指令等。正如你所说 - 这似乎是NPM的问题。 - marcin2x4
1
目前我在使用PS终端进行NPM操作。非常感谢您的帮助! - marcin2x4

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