I got my WSL2 up and running. On Windows level I installed node.js and now I want to run npm install snowflake-sdk
from Ubuntu level. Terminal returns -bash: /mnt/c/Program Files/nodejs/npm: /bin/sh^M: bad interpreter: No such file or directory
while PowerShell works fine.
Question is: is it possible to interact with Windows level installed applications using WSL2's terminal?
Note:
npm
on the Linux side, as per the official instructionsThanks, SeaDude. If you then need to call from Windows, you can usewsl npm ...
, but note that cross-file-system calls are generally discouraged in WSL2.harzvor's helpful answer provides good background information.
It is possible to make calling npm
from a Windows-installed Node.js copy from WSL2 work, though it's not obvious and a bit cumbersome - though you could wrap the workaround in a custom function or script:
# From WSL2; note the required use of '.exe'
node.exe 'c:/Program Files/nodejs/node_modules/npm/bin/npm-cli.js' install snowflake-sdk
The above, which relies on Node.js being installed in its default location on Windows, calls npm
indirectly, using essentially the same technique that the CLI entry point on Windows, the npm.cmd
batch file, uses.
Note:
In order to target a Windows executable from WSL, you must include the filename extension explicitly, such as node.exe
rather than node
.
Without it, e.g. with npm
, the Linux subsystem looks for an extension-less file by that name in the $PATH
folders, which does not work.
Such a file actually does exist even on Windows, but it is a shebang-based script designed for Unix-like platforms, and basically just dead weight in a Windows installation; the Linux subsystem still tries to execute it, but fails, because it uses CRLF (\r\n
) newlines rather than the expected LF-only (\n
) newlines. As a result, the unexpected CR that follows #!/bin/sh
(represented as ^M
in the error message) is considered a part of the executable path, so the invocation fails.[1]
Even fixing that problem manually (converting to LF-only newlines) doesn't help, however, because of how the shell script constructs the full path to the npm-cli.js
entry point: it expresses it as an UNC path that tries to target the Windows file-system location via the WSL file-system - e.g.,
\\wsl$\Ubuntu-20.04\mnt\c\...
- which is explicitly disallowed.[2]
Calling the batch file, npm.cmd
, explicitly, doesn't work either - neither directly nor with cmd.exe /c npm.cmd ...
:
*.cmd
file fails obscurely - not sure if that's a bug as of Windows 10 20H2.cmd.exe /c
it fails too, because cmd.exe
doesn't support UNC paths as the current directory and the WSL2-internal current directory path is invariably expressed as one (e.g., \\wsl$\Ubuntu-20.04\home\jdoe\project\some-project
).cmd.exe
defaults to the Windows directory in this case, so installation of packages to the current WSL directory('s project) won't work).Providing the full Windows-native path to the npm CLI's main .js
file to node.exe
, as shown above, works as expected, since Node.js seems to otherwise be handling UNC paths that refer to WSL2 file-system directories and files, such as the calling WSL2's shell current directory, properly.
[1] On Ubuntu 20.04, the CR in the shebang line itself no longer seems to be a problem, but the CRs in the remaining lines still are, so the invocation still fails, even more obscurely, which error messages such as : not foundram Files/nodejs/npm: 3:
.
[2] The reason is that the Linux dirname
utility is used to determine the shell script's own directory in order to determine npm-cli.js
's full path, and this utility by design operates from the perspective of the Linux file-system, which ends up expressing the script's Windows file-system location in this indirect, unsupported manner.
Yes, you can run notepad.exe
from WSL and it will open Notepad in Windows.
More documentation: https://learn.microsoft.com/en-us/windows/wsl/interop#run-windows-tools-from-linux
If I try running npm -v
in WSL, I get an error about it not being able to find a file:
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: []
}
The path to the file is mostly correct but it has appended C:\mnt
to it.
I managed to get around this by running npm
by giving Node the path to the npm-cli.js
file.
You can run:
node.exe \c\Program Files\nodejs\node_modules\npm\bin\npm-cli.js -v
But that runs into the same error.
I then tried this:
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
From here I was finally able to get some output from the NPM CLI.
From here I can install the package but it will likely be installed in the wrong location.
I couldn't seem to get npm
working from anywhere in the filesystem. This may be a limitation with NPM. Perhaps if you try messing with your path env vars, you can get it to work?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With