Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problems with Windows PATH variable getting imported #1890

Closed
mindplay-dk opened this issue Apr 12, 2017 · 32 comments
Closed

Problems with Windows PATH variable getting imported #1890

mindplay-dk opened this issue Apr 12, 2017 · 32 comments
Labels

Comments

@mindplay-dk
Copy link

I understand that the Windows PATH variable gets imported into the Linux environment on start-up.

I gather from poking through related issues that this is by design, I guess, with the idea of being able to run Windows executables from the Bash command prompt.

I was quit suprised to find that feature on the road-map. I honestly was not expecting that would be possible at all, and I'm not completely sure I understand how that's going to be useful in practice. I mean, even if they can launch, Windows applications aren't going to be aware of the Linux OS, so it seems a bit odd.

Either way, I find that the import of Windows paths into the Linux environment is causing a lot of practical problems.

For example, node and npm were immediately launchable from the Bash console, but I tried to npm install node-sass, which depends on a global installation of node-gyp, which I have installed globally on on Windows, but these tools are hardware and OS dependent, so it all just sort of blows up in your face.

Another example is composer, which was also immediately launchable from Bash, but I have plugins that cached various file-system paths in flat files with \ windows backslashes in the path, which caused errors. I have various tools installed globally, and I have the global Composer installation folder in my system path - simply importing that to Linux doesn't mean those tools will actually work.

I have lots of scripts and tools set up for my work routine in Windows, and these simply don't work, or get in the way and cause weird/unexpected results in Linux.

I understand that there's a registry work-around which I guess I'll try, but I wanted to open this issue to make you aware that, well, there are issues with this feature. Things that were designed to run under Windows, built for Windows, installed on Windows, etc. often have artifacts like cached data or binaries that don't simply work, even if you can get them to launch under Linux.

I think this feature is going to confuse a lot of Windows users. As others have pointed out, the name "Bash on Windows" is kind of misleading, because the Bash terminal is just a tiny front-end to a very large and complex Linux system behind it - I at least understood and expected this, some Windows users may not, but I never expected a feature like this, and I'm not sure it's useful.

What's more, I spent like two hours drilling through Linux startup scripts to figure out where these path variables were being set in the first place, and didn't find it - I guess they're "hard injected" into the Linux subsystem somehow at startup? I suppose that's why there's a registry key to toggle this feature. I was trying hard to get into "Linux mode", and was expecting to find an initialization like this in e.g. ~/.bashrc which I think is where the PATH variable is normally initialized?

Perhaps a better approach would be to inject the Windows path into a separate variable, e.g. WINDOWS_PATH, rather than injecting directly into PATH, and then initialize PATH in ~/.bashrc where I'd be able to see it and change it?

@benhillis
Copy link
Member

@mindplay-dk - Thanks for posting. You bring up many valid concerns, which is why I added the global opt-out registry key in the first place. We initially flighted this feature in Insider builds and I was fully prepared to pull the ripcord on this feature if a lot of people were having issues with it. However, my experience was much the opposite and most of the feedback has been overwhelmingly positive. I know a registry key isn't a very elegant solution and in the future different configuration options like this will be exposed in a more discoverable and user friendly-way. Alternatively you can also override your $PATH variable inside of your .bashrc file.

Let me try to address some of the specific issues you bring up:

  1. The majority of the issues you are experiencing are likely due to various scripts and tools not correctly handling spaces in the $PATH environment variable. These are uncommon on *nix but not illegal. In practice when using the $PATH variable (or components thereof) in a script you should wrap it in quotes.
  2. Could you please give a little bit more detail on how having node installed on Windows and inside WSL "sort of blows up in your face"?
  3. In order to invoke Windows binaries you have to fully qualify them, meaning you must supply the ".exe" extension at the end (even if they are in your $PATH variable). This makes it very unlikely that Linux tools will accidentally run Windows binaries.
  4. Regarding your "lots of scripts and tools" some specific examples would be helpful, I'd be happy to help you work through any issues you're experiencing and fix any bugs that come up in our implementation.
  5. Unfortunately the $WINDOWS_PATH variable wouldn't work without modifying user-mode Linux binaries to be aware of it.

Lastly I appreciate the feedback! I'm very proud of my work lighting up interop but know it isn't perfect. Regarding the feature's usefulness I will defer to our User Voice where this was one of the highest requested features.

@mindplay-dk
Copy link
Author

I will defer to our User Voice where this was one of the highest requested features.

Okay, if that's what people want, I suppose there's no arguing with that :-)

And I'm not "against" this feature per se, I just find it confusing, perhaps because I think more of UOW as being a tool that enables me to comfortably run Linux tools with closer integration to Windows compared with Docker or an emulator - I guess some people (possibly the majority) may think of it more as better alternative to Git Bash in that it also happens to run Linux binaries.

I guess the latter mode of thinking is what you inspire by naming it "Bash on Windows" :-)

Could you please give a little bit more detail on how having node installed on Windows and inside WSL "sort of blows up in your face"?

Yeah, it kind of comes back to your next comment:

In order to invoke Windows binaries you have to fully qualify them, meaning you must supply the ".exe" extension at the end (even if they are in your $PATH variable). This makes it very unlikely that Linux tools will accidentally run Windows binaries.

True, but most tools these days are not in fact binaries - npm, node-sass, tsc, gulp, composer and phpunit to name a few that I use.

Of these, at least npm, composer (or possibly a Composer plugin) and node-sass failed in some way, and I ended up installing the Linux versions (which take priority in the PATH) anyhow.

The oddest thing about the Node-related issues, was that some node-sass dependencies that had already been installed in node_modules while on Windows couldn't run - and then, even after erasing node_modules to start over, the node-sass package wouldn't install because of platform differences with the installed node-gyp build environment.

Replacing any globally-installed node/gyp/node-sass packages on my Windows drive obviously would be very bad if I ever try to run any of it from a plain Windows shell again, so I ended up creating a Linux install of node/npm/gyp anyway.

But even if I avoid global package installations and install locally in node_modules instead, I'll need separate project-folders for the Windows and Linux versions of every project I'm working on, since any binaries that end up being built to the node_modules folder must have the same hardware/OS architecture builds of their dependencies, so it just doesn't work well, for me, personally, in practice.

Anyhow, overriding the PATH variable in ~/.bashrc is probably the simplest and most correct option, so I will just do that :-)

I guess you can close this issue, though I'll just put one thought out there: maybe importing some paths, such as C:\windows\system32, is okay - but maybe the import needs to be a bit more selective to be really useful? Not sure, I guess that's not really possible, since the path variable is just a variable - we don't really know anything about the paths other than their priority, so there's probably not much we can do...?

@therealkenc
Copy link
Collaborator

since any binaries that end up being built to the node_modules folder must have the same hardware/OS architecture builds of their dependencies, so it just doesn't work well, for me, personally, in practice

@benhillis - It is kind of an existential question WSL will have to face eventually. It isn't just Node.js. Say you are a Java programmer. You have the same kind of problems as @mindplay-dk's quote above. Did you mean Java backed by a bunch of win32 native libraries built with msvc? Or Java backed by a bunch of Linux native libraries built with gcc? Ditto Python, which is what the guy over in #1370 is struggling with presently.

I am sure you have a handle on all this in your head. +1 for the pure awesomeness that is WSL interop. But it is going to be rough sailing with a lot of confusion for while.

@aseering
Copy link
Contributor

aseering commented Apr 12, 2017

@mindplay-dk -- I think you've missed a point about binaries, and as such have not entirely answered @benhillis 's question. Namely: In Windows, if it doesn't have a file extension, it ain't gonna run :-) It may be a .exe file, in which case it will execute directly. It may be a .js, or .php, or (etc); in all of those cases it will be invoked with the correct interpreter. Windows will often let you omit the extension when running the program. But it's still there.

As a result, something like phpunit CAN NEVER be a valid Windows executable name because it lacks a file extension entirely. So, if that's your program's name (as seen on WSL's $PATH), it should be unambiguously the Linux version of that program.

So what you're telling us is that you have a Windows application that is creating scripts that are not valid Windows scripts, and putting them in Windows %PATH%. That's just weird :-) To me, the obvious follow-up questions are (1) which app, and what scripts?, and (2) why is it doing that?

@mindplay-dk
Copy link
Author

In Windows, if it doesn't have a file extension, it ain't gonna run :-)

Well, usually, the way these things are wired on Windows, there's an auto-generated .bat file somewhere - typically right next to "binary", e.g. JS/PHP/phar/rb/etc. script without a file-extension (and with a hashbang) that Windows can't find, but Linux will.

I believe tools such as Composer do that as a work-around, so that end-users don't have to hand-write a .bat file for every package - so e.g. Composer can deploy the Linux "binary" (hashbang script) next to a matching .bat file.

Is it weird that the .bat and the "binary" end up in the same folder? It's not a problem on Windows, because it won't launch the "binary" without the proxy .bat. I guess it deploys them both to the same folder just for simplicity - I guess there was no need to introduce a platform difference and put the binaries in a folder outside of paths, since Windows won't find them either way.

Perhaps one reason they keep it that way, is so that e.g. Git Bash (which I have been using for a long time) will actually skip the .bat and go directly to the "binary", since Git Bash also imports the Windows PATH variable. I'm just making wild guesses here, but it makes sense so me ;-)

@mindplay-dk
Copy link
Author

aaand, there you are :-)

@mindplay-dk
Copy link
Author

And here's npm doing a similar thing - it uses this package to do it.

Likely package managers for other scripting languages (ruby, perl, python) are doing similar things?

@aseering
Copy link
Contributor

aseering commented Apr 12, 2017

Hm -- that's a good point, and I think a good use case.

I haven't run into this with Python (which I use a bunch personally), perhaps because it's slightly more common in Python-land to install as a module and invoke as python -m <modulename> <args>; nor with node because I always do local installations for node packages. (I was told once by an opinionated Node connoisseur that global node package installation is a Bad Thing(tm) and I haven't cared enough to date to go validate their justification :-) )

(Your point about Windows and Linux local node installations conflicting is a good one, and has been made on other tickets before. It's particularly bad because even simple .js files, which usually ought to otherwise be platform-independent scripts, don't work because Linux node is incompatible with the newlines used by Windows node.)

It seems to me that Windows can't directly execute these extension-less files, and Linux (meaning, code run within WSL) hasn't tried to mark them as executable. So perhaps this could be addressed in a future iteration of DrvFs, by not setting the execute flag on files in that case? Just a thought -- Linux tools will generally ignore files in $PATH if they aren't marked as executable.

@john-osullivan
Copy link

I think this bug is giving me Python issues. Currently trying to set up the ebcli in WSL; pip installs it fine, but when I try to run something like eb logs from within the repo, I get an error like:

-bash: /mnt/c/Users/Fu/AppData/Roaming/Python/Scripts/eb: c:\python27\python.exe: bad interpreter: No such file or directory

It looks like the Windows Python path is beating the one I set in ~/.profile. Any ideas on how to get around this?

@TheFirstDeity
Copy link

TheFirstDeity commented Jul 29, 2017

Looks like the same problem I was having. Lots of package & script bins don't have file extensions, so the Win version might get executed if it gets found first. Some people fix it by pre-pending their Linux entries to the PATH var so they always come first, but I think sometimes it's better to remove competing Win paths (especially when they provide identical function.) I added this to my ~/.bashrc for now (it could be improved, but I'm still a newbie.)

Function Source: Removing a directory from PATH

### remove unnecessary Win PATHs
# This can prevent extension-less commands from bleeding into BASH.
# (eg. "ng" would execute the Win bin if "@angular/cli" wasn't installed on Linux.)
#
function path_remove {
  # Delete path by parts so we can never accidentally remove sub paths
  PATH=${PATH//":$1:"/":"} # delete any instances in the middle
  PATH=${PATH/#"$1:"/} # delete any instance at the beginning
  PATH=${PATH/%":$1"/} # delete any instance in the at the end
}

path_remove '/mnt/c/Users/me/AppData/Roaming/npm'
path_remove '/mnt/c/Users/me/AppData/Local/Yarn/bin'
path_remove '/mnt/c/Program Files (x86)/Yarn/bin'
path_remove '/mnt/c/Program Files/Git'
path_remove '/mnt/c/Program Files/Git/cmd'
path_remove '/mnt/c/Program Files/nodejs'
path_remove '/mnt/c/OpenSSL-Win32/bin'
path_remove '/mnt/c/Program Files (x86)/Python27'

@john-osullivan I noticed that with npm packages I could end up running the wrong version if I simply forgot to install it on WSL too, since it will then use the Windows one (even with paths in the right order.) You could try removing Windows' python/ebcli paths from your bash env like I did, coz why would you need access to both versions at the same time?

@grantcarthew
Copy link

I just started looking at the Windows Subsystem for Linux feature now. I had this issue with Node.js and npm.

As stated by @mindplay-dk in the top post, I disabled the Path import feature using the registry key. To clarify for anyone having the same problem. Disable the feature by closing the bash shell, create the DWORD registry key, run the bash shell. If you then type echo $PATH you will see the Windows paths have gone.

I agree with @mindplay-dk, this seems like a backward feature. I think it depends on where you are coming from. I have been working with Linux for many years and do not expect windows binaries in my Linux path. I imagine people who have mostly worked with Windows would expect to be able to run notepad.exe from any command prompt.

This should be an Opt-in rather than an Opt-out feature.

@benhillis
Copy link
Member

@grantcarthew - I think you nailed it, it depends on where you are coming from. I hear all the time that having NT paths imported to WSL is peoples favorite feature and they love it. Conversely, I also hear from others that it breaks their makefiles or other scenarios. I think the problem is these features are hidden behind some not very well documented registry keys. I'll create a work item to come up with a better way to set up various WSL configuration options.

Thanks for the feedback.

@shaynem
Copy link

shaynem commented Aug 8, 2017

Just ran into this issue myself where running npm and nodejs were picking up the windows versions - modified the bashrc to fix it - But took me some figuring out before fixing it which lead me here - Just writing to +1 on making it better configurable - as it's not something I was expecting to come across.

Not per say an issue: Other then turning WSL on in windows - thats the only option I know exists for it.

@megakoresh
Copy link

Can confirm that both n-install AND rbenv suffer from this problem

@ciwolsey
Copy link

ciwolsey commented Sep 26, 2017

Suffering the same issues as everyone else while trying to use Nodejs. IMO it's not worth polluting PATH in Linux just so we can run Windows apps. Managing PATH manually via bashrc seems like it could get tedious. I heard there's a registry switch for it and will probably use that but I feel strongly there should be an option to turn it on, but have it turned off by default. As others have said, it's not rare in Windows to have a command that's exactly the same as it's Linux counterpart.

@spences10
Copy link

So, can you add an alias in ~/.bashrc for this?

I think I have made a mess because I have installed node via Linuxbrew thinking that it would solve my $PATH issues

Is there a solution to this? I'm thinking about doing another install of WSL via the Windows insiders channel, I had it switched on as a beta feature before

@mloskot
Copy link

mloskot commented Oct 23, 2017

Alternatively to the path_remove solution in #1890 (comment) it seems possible to completely disable appending NT PATH to #1493 (comment)

@spences10
Copy link

My machine has gone off for an RMA now so I'll have a fresh and clean install to play with when it comes back 😄

@eviktorovich-sc
Copy link

eviktorovich-sc commented Oct 27, 2017

@AndrewPardoe
Copy link

I ran into an issue with the Windows path in my bash environment twice.

The second issue was a makefile getting confused on a path that contained embedded parentheses and spaces. While these are legal in Linux filesystems, they are rarely used. The correct fix was in the makefile.

The first issue was more insidious. I had Strawberry Perl on my Windows path. It's built with MinGW. Because Perl allows C interop, Strawberry Perl includes the MinGW C++ stdlib. I also have GCC on my Ubuntu install. GCC just searches the path for a compatible stdlib. When compiling I found that GCC would pick up the MinGW stdlib, which looks like a GCC stdlib, because it was first on the path. The fix was to switch to ActiveState Perl : )

I run one node.js app on WSL (Matt Godbolt's Compiler Explorer) and haven't seen any weird issues with node.

@benhillis
Copy link
Member

The ability to disable this behavior via wsl.conf has been added to build 17713.

https://docs.microsoft.com/en-us/windows/wsl/wsl-config#interop

@mindplay-dk
Copy link
Author

@benhillis IMO this should be disabled by default.

Simply importing the Windows path and expecting meaningful results is a little bit bonkers - even if that works some of the time, for certain things, the results are pretty random, since there's no guarantee that if/when something works, it works for the right reasons.

For example, I just realized Linux has been picking up my Composer global bin-folder and running scripts I installer under Windows with a different version of PHP under Linux - obviously, it has all the wrong dependencies installed, for the wrong version of PHP, and eventually failed hard.

Same would be the case for Node, Python scripts, etc. - just passing paths from the Windows environment to the Linux environment and expecting meaningful results is a little bit naive, isn't it?

@molxyz
Copy link

molxyz commented Sep 21, 2018

@mindplay-dk Try this to see if it can work for you:
PATH=$(echo "$PATH" | sed -e 's/:\/mnt.*//g') # strip out problematic Windows %PATH% imported var

@mindplay-dk
Copy link
Author

@molxyz thanks, for now I'm working around this by prepending my Linux search-paths to make sure they "win" over the imported Windows paths - I understand there's an option to disabled this feature in the next version anyhow.

@molxyz
Copy link

molxyz commented Sep 23, 2018

@mindplay-dk Ah cool.. I'm using Ubuntu 18 Bionic. I hope Ubuntu will have this option, great to hear. Thank you.

@dakahn
Copy link

dakahn commented Jul 15, 2019

Just wanted to leave a note here for future devs 👩‍🚀 -- if you get rid of your Windows path imports in WSL via any of the above mentioned methods, it seems to break some functionality like launching a Storybook on a local sever.

Just a heads up 👍🏽

@b-hayes
Copy link

b-hayes commented Nov 29, 2019

I personally have not had any issues at all with this.

My tools installed in wsl will always take precedence over a windows one.

eg. composer in wsl will only run the linux version. I have to type composer.exe to run the windows one.

As to why this is an advantage one example I'd give is that git in linux can use the windows git credentials manager with native windows secure credential storage while still having its own configs separate form git in windows.
Or simple launching native applications from wsl is handy as well or having bash scripts that can execute powershell commands or start apachee services in windows etc etc. Its really very handy indeed.

@danon
Copy link

danon commented Nov 20, 2020

You can also run it from cmd, instead of bash

# Run from bash from WSL2
danon@desktop:~$ npm -h
bash: ./mnt/c/Program Files/node.js/npm: No such file or directory

# Run through cmd
danon@desktop:~$ /mnt/c/Windows/System32/cmd.exe /C npm -h

Usage: npm <command>

where <command> is one of:
    access, adduser, audit, bin, bugs, c, cache, ci, cit,
    clean-install, clean-install-test, completion, config,

It's a little slower, but paths are guranteed to work, since it's actually Windows shell that runs it.

@LuDColl
Copy link

LuDColl commented May 2, 2021

Just add export PATH="$PATH:/usr/bin" to the end of ~/.bashrc, so that usr/bin takes precedence over windows' apps. Probably not a good option.
insignar in the stackoverflow


That was the only method that worked for me

@MartyMcFlyInTheSky
Copy link

MartyMcFlyInTheSky commented Mar 22, 2023

I'm siding 100% with @mindplay-dk on this issue. I just experienced problems with installing a framework on Windows and WSL simultanously, which caused the WSL to mix up the path variables (which are in turn used to install certain programs). This was unexpected behaviour to me and I would have thought that those environments would run more secluded. Also, I don't really see the benefit of this feature other that I can run explorer.exe or code . from the get go. I think it's more intuitive to hook up explorer.exe and other apps inside your .bashrc as an opt-in.

I did this (as a recap):

  1. create new file wsl.conf in /etc
  2. add [interop] section (if it doesn't already exist):

/etc/wsl.conf:

[interop]
appendWindowsPath=false

This prevents wsl startup to append Windows paths to the linux path variable.

  1. open .bash_profile and add aliases to regain the convenience of launching explorer.exe and vscode anywhere (adapt to fit your user):
alias code="/mnt/c/users/<user>/appdata/local/programs/'microsoft vs code'/code.exe"
alias explorer.exe=/mnt/c/windows/explorer.exe
  1. close out of wsl. Wait 8 seconds for it to completely shutdown. To check if wsl has shut down completely you can query it (in windows powershell):
    wsl --list --running
    Wait until there's no "Ubuntu" anymore (or whatever your linux distro is that's running on your WSL). If it doesn't shut down, you can also do wsl --shutdown (NOTE: this will shutdown all WSL processes)

  2. Restart WSL. Your environment variable should be gone. Check with

echo $PATH

There should only be distro related paths now :)

@b-hayes
Copy link

b-hayes commented Mar 23, 2023

[interop]
appendWindowsPath=false

The name of this setting indicates the problem perhaps it should prepend not append.
Distro should always have its own paths first so nothing breaks.

@handsomefox
Copy link

As was described here by @MartyMcFlyInTheSky, VSCode can be added as alias even when setting appendWindowsPath=false using:

alias code="/mnt/c/users/<user>/appdata/local/programs/'microsoft vs code'/code.exe"

This has a problem, though. VSCode will tell you:

When working on folders in wsl, we recommend to use a WSL window.
In a WSL window, all commands, extensions and the terminal run in the Linux subsystem. 
To switch to a WSL window, use Reopen Folder in WSL

But, if you set the alias like that:
alias code="/mnt/c/users/<user>/appdata/local/programs/'microsoft vs code'/bin/code"
The VSCode will be opened "properly" and won't annoy you with the message.

I know the thread is ancient, it's just that I had to do this exact thing myself recently and had to do a bit of googling and reading to find an answer, since having appendWindowsPath=true makes tab-completion incredibly slow, so hopefully my answer helps somebody, too, as the previous answer by @MartyMcFlyInTheSky did for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests