BASH on Ubuntu on Windows (AKA Linux Subsystem for Windows) 10 - How do I set my PATH?

Thanks to the Anniversary Update, I now have BASH on Ubuntu on Windows 10. Previously, I used Cygwin, and had set up Maven in Cygwin, (and got it fully working), which largely consisted of installing Maven, and then modifying my PATH environment variable (in ~/.bashrc)

Well, I'm trying to do the same thing using BUW, but as far as I can tell, the PATH variable is ignored (adding the Maven bin directory to the PATH, and then executing which mvn returns blank). Is there a trick I'm missing, or do I have to set up my PATH differently in BUW?

EDIT:

Let me be specific. What do I need to do in the "???" step to get pathTestScript.sh onto the path?

mkdir -p ~/pathTest
touch ~/pathTest/pathTestScript.sh
echo '#!/bin/sh' >> ~/pathTest/pathTestScript.sh
echo 'echo "it works!"' >> ~/pathTest/pathTestScript.sh
bash ~/pathTest/pathTestScript.sh
    # Should output 'it works!'
# ?????????
pathTestScript.sh
    # Should output it works!'

EDIT 2:

I want to be very clear with my actual, final goal. I've got a JDK and Apache Maven installed on my system in the usual places. I had both of these working perfectly fine in Cygwin. Now that BUW is out, I want to use them in there instead, but I can't figure out how to set up my environment for them, as any changes I make to my PATH don't seem to have any effect.

EDIT 3:

Ok, Now I'm concerned I'm on a wild goose chase. If I do echo $PATH, I get /mnt/c/Program\ Files/apache-maven-3.3.9/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

That's what I expect. That's what I put in my ~/.bashrc file... Then I do ls /mnt/c/Program\ Files/apache-maven-3.3.9/bin and I get

m2.conf  mvn  mvn.cmd  mvnDebug  mvnDebug.cmd  mvnyjp

But when I do which mvn, I get blank, and if I invoke mvn, I get redirected to use apt-get to install it.

So the issue isn't that the PATH isn't being updated... it's just being ignored. Is there a way to get it to pay attention to the PATH? If not, this is a pretty weak version of Linux (IMO)

EDIT 4:

It's been brought up a couple times, and yes, my slapped together example forgot to mark the file as executable. In my real-world scenario (with Maven), the files are all executable:

cd /mnt/c/Program\ Files/apache-maven-3.3.9/bin && ls -alt
total 36
dr-xr-xr-x 2 root root    0 Apr 19 11:56 ..
-r-xr-xr-x 1 root root 1843 Apr 19 11:56 mvnyjp
dr-xr-xr-x 2 root root    0 Apr 19 11:56 .
-r-xr-xr-x 1 root root 1815 Apr 19 11:56 mvnDebug
-r-xr-xr-x 1 root root 7383 Apr 19 11:56 mvn
-r-xr-xr-x 1 root root 1513 Apr 19 11:56 mvnDebug.cmd
-r-xr-xr-x 1 root root 6067 Apr 19 11:56 mvn.cmd
-r-xr-xr-x 1 root root  230 Apr 19 11:56 m2.conf

Solution 1:

Update Summary

The executables in question are not linux native format (ELF), they are compiled for windows. During path expansion, bash checks the magic number of the binary, if it's not a match for ELF, it doesn't expose it via path expansion. However, bash for windows did include a capability to launch native windows applications from the bash environment, which is why direct execution (without path expansion and subsequent binary check) works fine.

Resolution is either an alias based .bashrc addition (or any number of alternative methods to mimic path expansion thus bypassing bash file evaluation) or installation of the linux version.


Original answer

File Permissions

It's possibly a cross file system permissions issue. If you cd /mnt/c/Program\ Files/apache-maven-3.3.9/bin and try to run mvn like so ./mvn what happens?

What is the output of ls -alt in that directory?

If the file isn't properly marked as executable, it won't show up as a 'program' on your path. If it's a binary file and not in the 'linux' format (ELF) then it will also not show up as a path executable.

If directly executing mvn doesn't work (please post the ls results), try adding execute permissions chmod ug+x mvn

Wrong version installed

Are you sure you have the linux native version installed - the same version you used with cygwin will almost definitely not work.

You can check binary compatibility with sudo apt-get install elf-binutils then on the file mvn use the command readelf -a mvn If you get an error such as 'Not an ELF file...` then you have your answer.

I just noticed that you didn't add execute permissions to the test shell script in your example, which (unless you simply forgot to list the step), completely explains that particular failure.

Summary:

  1. Make sure the executables in the maven bin directory are properly set as executable by using chmod. Post the output of ls -alt in your answer.
  2. Make sure you have a linux binary - use the utilty readelf to verify.
  3. Run your shell script test again, but this time mark the file executable.

Update

The path issue was a red herring; you are just trying to execute a binary format that is not compatible with the linux on windows environment.

On the surface the two environments (cygwin and bash on windows) provide a somewhat similar user experience but the implementation and resulting binary compatibility are very different.

Bottom line - Cygwin and Linux binary formats are not compatible. You need to install the linux native version to run it from bash on windows. You could also compile it from source inside the bash on windows environment; but due to the 'early days' nature of the environment I'd worry about chasing dependencies.

Brief description of the two environments:

Cygwin is effectively a translation layer that provides an API for system calls that are typically not available on non-POSIX systems, which allows you to compile many programs written to run on linux in the windows environment. However it is still running in a 'windows' environment - that binary will now only operate in the cygwin environment on windows. This translation layer and associated libraries allow source code written against the Linux API to be compiled in the cygwin environment and run on windows. Binaries built in this manner will not run on Linux or Windows natively; only in the cygwin environment.

The bash environment on windows provided by canonical is much different than cygwin. It actual 'recreates' an environment for a program that appears to actually be linux - i.e. the standard libraries are available along with POSIX system calls - without requiring any modification to the binaries. In many cases a binary built against ubuntu can be copied directly to the bash on windows environment and run without any issues.

To be recognized as a valid executable in bash on windows it needs to be in a native linux binary format or a script file marked with the program to interpret it (for a bash script, #!/bin/bash). A native linux binary will have been built against linux libraries and system calls. Bash confirms that something is a valid executable both by checking the executable permission bits and checking the binary file format is compatible (a 'magic number' check). If it's a binary file and isn't in ELF format, it isn't exposed to the shell via path expansion.

To make this issue harder to clarify, they have added partial ability to launch native windows applications from bash on windows, but clearly didn't address the bash path expansion binary file format check - or they did and it's a bug.

Second edit:

Clarification on your question:

When you launch it directly (./mvn) it bypasses the Bash evaluation and just executes it. The bash on windows environment is smart enough to launch windows native executables, which that must be. I don't believe a cygwin binary would launch properly from bash, but I could be incorrect - documentation is meager at this point and I don't have a test environment accessible right now.

Workaround that provides equivalent capability to 'path' support:

If you are otherwise entirely happy with the maven installation (no other compatability issues, everything just 'works'), but having it on the path is important, you can use a simple workaround which will provide equivalent capability.

In your .bashrc file, add the following alias:

alias mvn='/mnt/c/Program\ Files/apache-maven-3.3.9/bin/mvn'

Repeat the equivalent for any other executables in that directory you want access to from anywhere within the bash on windows environment.

restart bash or source the file, and then mvn will work from any directory (based on your statement that direct execution from within the bin dir, ./mvn, was working).