-
Notifications
You must be signed in to change notification settings - Fork 847
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
Native wsl shell behaves differently from ssh login to wsl #4911
Comments
Several approaches, most common being
I could not follow this sentence, but not being able to follow academic in the context. The reason These are not work-arounds, they are by-design |
Maybe i was not clear. On a "standard" linux system there is not much of a difference whether you login "local" or remote via ssh. I am not saying that there are no differences at all, but at least most of the environment variables are identicall. This is also for PATH Unfortunately this is different for WSL: If you start a local shell, %PATH% is "injected" into the shell. Also WSLENV is taken into account. If you login via ssh, this is not the case. If this cannot be fixed by default, is it possible to somehow activate this mechanism optionally? What/where is the magic that a "local" login shell do special handling for PATH and is also interpreting WSLENV?
If you replace the standard shell /bin/bash in the passwd file to >mntp>/windows/system32/bash.exe, at least the PATH is initialized according to %PATH%. I thought, that system32/bash is part of WLS but as of now i think i am wrong, so I cannot really recommend this anymore |
You face the same problem when you try to ssh into a Linux VM, running inside another Linux, which would represent a similar scenario as WSL . For example, running Alpine as a VM on top of Ubuntu! You won't be able to access Ubuntus $PATH and Ubuntus executables from within Alpine. |
But that's exactly what's actually happening if you start a WSL shell on Windows - not using ssh: You will find a $PATH which contains host related pathes:
In both cases i start on the HOST system and start a shell on the guest. But the environments are different. The same difference applies for $WSLENV and all variables specified within WSLENV I am not against this special handling of PATH end WSLENV. It is quite usefull in sharing things between the two worlds. I just wonder how to achieve the same (or similar) when "entering wsl" via ssh |
You were pretty clear except for the part about putting a win32 program in your
Correct. This is by-design
"This" behavior of You can coerce There are other approaches as well.
The magic happens in
Windows |
Just out of curiosity... why would you even want to ssh into WSL, when you can have all the functionality available directly? |
Because i often work remotely on that system. As i am more linux than windows, i love to work in terminals and RDP is not really an option. For many years i have been using Cygwin and was quite happy despite "its" huge fork problem... Then i tried to switch to WSL. I currently use Ubuntu, VcXserv and Terminator and i am quite happy. I use WSLENV to share some variables like JAVA_HOME and MAVEN_HOME in combination with some little helpers. This way i can use the Windows-installed versions of Java and Maven. I don't like to have each installed twice and need to keep them in sync. All this works very good in "local" WSL. Of course i can use things like ,ssh/environment to fill the gaps, but then again i am duplicating configuration. So i am very thankfull for all the input of you both so far :-) I am currently trying to implement a workaround (and of course will post it here once it would work), but currently have an issue with part of the solution. Here's how to reproduce:
Unfortunately this freezes the konsole. Is it possible to make this work? Interesting fact: If i ssh into WSL from a real linux server (or maybe it is just because it is a different host and not the host running WSL), then the above command works and returns. |
Wow, a hell of a setup you've there. I'd suggest to reconsider that. WSL isn't actually intended to be used with VcXserv since it's not optimized performancewise for that. Maybe moving your entire setup to WSL only, and switching to VSCode might be a solution. I'm not a Java developer and don't know if it provides all the necessary things you need, but take a look here. Also, VSCode has a great remote extension which let's you work directly in WSL or via ssh. So when you're on your Windows machine you can use VSCode directly with WSL. When you're remote, you can ssh with VSCode into your WSL. |
I was able to reproduce the above. Noting that bringing up unrelated topic under the same issue umbrella usually ends badly. That'd be a pretty legit submission given a filled out bug template. FWIW I am pretty sure I've tried this scenario in a past life and it worked. This might be a regress. Or I am imagining having tried. Which is also a pretty good possibility. This does work: Critical difference in scenarios being, that's a Linux |
That particular issue is addressed with Win32-OpenSSH version 8 available here. The sensible (or at least pragmatic) answer to the OP remains quoth "append the Windows path yourself in
Or if one were inclined, schmancy:
YRMV. |
Hi @therealkenc , thanks for your answer. Based on your idea to have an scripted solution I developed an own script which not only takes PATH intro account but also correctly handles WSLENV (inluding the /u, /w, /p and /l options). See https://devblogs.microsoft.com/commandline/share-environment-vars-between-wsl-and-windows/ for more information about WSLENV. Add the following code somewhere at the beginning of your
Looks like There is some issue with the vbscript code: It doesn't expand placeholders used within the environment variables values, e.g. ComSpec would resolve to |
For
Noting, critically, that I don't personally advocate doing anything like this. I'd (in arguendo1) set [1As an aside, calling Windows Java from WSL is a red flag, but okay free country and that's not your ask.] |
For some reasons this does not work for WSLENV (tested with having no .bash_profile at all, just your code):
Such lilke calling Linux software/WSL from within Windows :-P No seriously, why is this a red flag? |
Hi @therealkenc in your last post you've used wsl.exe to start bash, but not ssh. A login via ssh looks like this for me: (WSLENV is a environment variable in USER space on my system. Maybe the ´cmd.exe /C echo %VAR%` trick only works for SYSTEM?)
This is different with vbscript approach. |
Right I see what is going on there. If you actually want to marshal local environment variables from the client, use Alternately you need It gets worse. Since we are evoking
I can't get the "vbscript approach" to work with a local cmd
[edit] To clarify, you'd (in the hypothetical) boostrap |
On reflection, it is not obvious to me why, if one were doing the magic
|
This is not my point. I don't want to have local variables on the remote side. I just want to have the environment in shells running on that host to be the same, independetly of logging in on that host via ssh or "locally" via wsl.exe.
Dito: This is not about temporarily "set" variables. It's just about the base environment, so only those variables which are available if you just open an ordinary local cmd.exe.
Good point! :-)
Yes, it is only ment for the base environment variables.
As i wrote before, i cannot get
I am not sure if i understand this approach: If i would define it only in .bash_profile, then this would only work for cmd.exe instances, started from within WSL. The same then also applies to those variables mentioned within WSLENV. I think the whole mechanism is based on the fact, that there is a HOST and GUEST system. In my opinion, it would be best if wls.exe wouldn't do any PATH or WSLENV magic. Instead there should be something like a "wsl-injectenv.exe". Then it would be up to user to have it executet in its .bash_profile. As a result the environment would be the same for all bash instances, be them locally instantiated or from remote. This has been quite a long discussion right now, and I am quite thankfull that you still keep track, btw... :-) |
No. It is equivalent to fetching the keys (sic) enumerated in
[What this is all about is... redacted :).] The keys (sic) you want injected would be defined once, since there's no reason to define In any case fetch
I cannot reproduce this. That's why I picked HKCU/Environment Noting that getting User and System variables to take can be a PITA, because they're cached all over creation. When in doubt, reboot.
You mean
YW happy to keep at it. |
Reboot was not required, but i always thought it would be enough to restart the "starting point" of my experiments after modifiying some windows environment variables. In my case, the starting point is the first cmd shell from which i run the ssh command. But i was wrong: The cmd.exe started from within wsl is a child of the wsl system. As long as this system is not restarted, environment changes are hidden. So, closing all wsl dependen windows/processes (including sshd) is required. Interestingly, the vb code does not suffer from this. Thanks again for you patience. After some testing period i will post my final solution here. Maybe there are some other crazy people like me... ;-) |
Here is my final solution. Add at the beginning of #!/bin/bash
if [[ -n "${SSH_CLIENT}" ]] && grep -q '([email protected])' /proc/version ; then
#source the output of the following code. this construct is mainly to have those functions temporarily in a subshell
. <(
function translatePath {
local WINVAL="$1"
/bin/wslpath -u "$WINVAL"
}
function translateList {
local LIST="$1"
while read -r component; do
TRANSLIST="${TRANSLIST}""$(translatePath "$component")":
done < <(echo "$LIST" | tr ';' '\n')
echo "$TRANSLIST"
}
function getWinPath {
/mnt/c/Windows/System32/cmd.exe /c echo %PATH%
}
function getWinVar {
local WINVAR="$1"
VBS=$(mktemp -p "$HOME" .XXXXXXX.vbs)
cat > "$VBS" << INP
Set oShell = WScript.CreateObject("WScript.Shell")
Set fso = WScript.CreateObject("Scripting.FileSystemObject")
Set stdout = fso.GetStandardStream (1)
Set oEnv=oShell.Environment("User")
var = oEnv.Item( "$WINVAR" )
If var = Empty Then
Set sEnv=oShell.Environment("System")
var=sEnv.Item( "$WINVAR" )
End If
stdout.WriteLine(oShell.ExpandEnvironmentStrings( var ))
INP
VBSWIN=$(wslpath -wa "$VBS")
/mnt/c/Windows/System32/cmd.exe /c cscript /b "$VBSWIN"
rm -rf "$VBS"
}
function doOptionL {
local VAL="$1"
translateList "$VAL"
}
function doOptionP {
local VAL="$1"
translatePath "$VAL"
}
export WSLENV="$(getWinVar WSLENV)"
echo export PATH=\""$PATH:$(doOptionL "$(getWinPath)")"\"
echo export WSLENV=\""$WSLENV"\"
IFS=':' read -ra VARS <<< "$WSLENV"
for i in "${VARS[@]}"; do
IFS='/' read -r var opt <<< "$i"
if [[ $opt = *w* ]]; then
: #ignore
elif [[ -z $opt || $opt == u ]]; then
echo export \""$var"\"=\""$(getWinVar "$var")"\"
elif [[ $opt == *p* ]]; then
echo export \""$var"\"=\""$(doOptionP "$(getWinVar "$var")")"\"
elif [[ $opt == *l* ]]; then
echo export \""$var"\"=\""$(doOptionL "$(getWinVar "$var")")"\"
else
echo unsupported case for >&2
fi
done
)
fi |
@DrVanScott Thanks for that script. Have you updated your script since? You have it in a GitHub repo or even a Gist? |
I noticed in wsl2 Ubuntu 22.04.4, this problem on the PATH variable could be solved by running /mnt/c/Windows/System32/wsl.exe through ssh. Then you can open Windows program through ssh. But WSLENV variable is still missing. I am not sure where WSLENV is set to a value in nowdays version. If I open a cmd.exe from Win+R, and |
If I start a native WSL shell, i can
If i login to WSL via ssh, both of these actions behave not the same
The latter issue can be worked around by using "/windows/system32/bash.exe --login" as login shell
Any workarounds to solve both issues higly recommended.
EDIT: Solution can be found here: #4911 (comment)
The text was updated successfully, but these errors were encountered: