My bash knows what PATH is:
pkonl@Hedwig MINGW64 ~/ (main)$ echo $PATH
/mingw64/bin:/usr/bin....
However, starting a julia somehow makes the bash lose that information:
pkonl@Hedwig MINGW64 ~/ (main)$ julia
_
_ _ _(_)_ | Documentation: https://docs.julialang.org
(_) | (_) (_) |
_ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version 1.8.1 (2022-09-06)
_/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |
julia> run(`echo $PATH`)
ERROR: UndefVarError: PATH not defined
Stacktrace:
[1] top-level scope
@ REPL[1]:1
Does anyone know why?
Julia is trying to interpolate the value of a Julia variable PATH
4 Likes
oheil
September 26, 2022, 4:13pm
3
Thats not bash, which produces the error but Julia trying to interpolate PATH:
julia> run(`echo $PATH`)
ERROR: UndefVarError: PATH not defined
Stacktrace:
[1] top-level scope
@ REPL[1]:1
julia> PATH="XXX"
"XXX"
julia> run(`echo $PATH`)
XXX
â[0mProcess(`â[4mechoâ[24m â[4mXXXâ[24m`, ProcessExited(0))
(ninjad)
oheil
September 26, 2022, 4:16pm
4
What you want to see or test is this:
julia> run(`bash -c "echo \\\$PATH"`)
There is quite some effort to escape everything which is involved.
Why?
First, run
doesnât call a shell (e.g. bash) but executes the commend directly: Running External Programs ¡ The Julia Language
So, your attempt doesnât run a bash, but (for me) /bin/echo
:
julia> run(`bash -c "which echo"`)
/bin/echo
Process(`bash -c 'which echo'`, ProcessExited(0))
Second, just escaping single with \$
is not enough. It just escapes Julias string interpolation. The bash, which is called sees $PATH
and would again put the value of this variable, which results in something like:
echo /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin....
For me, this gives an error because I have some special characters in some paths. So, to avoid this, triple escaping:
\\\$PATH
which is equivalent to
\${PATH}
because you already avoided Julias string interpolation with ${PATH}
, so only a single escape is enough now.
1 Like
Thanks, but this does not work. This does:
run(`bash -c "echo \${PATH}"`)
Edit: Wow, quoting code with backslashes really IS fiddly.
Palli
September 26, 2022, 4:30pm
6
FYI: The ENV isnât forgotten, you can also do at least this way (only bash interpolates with shell ENVs, and run doesnât why you did what you did, but bash might not even be available, so this way might be preferable, and more portable):
P=ENV["PATH"]; run(`echo $P`)
2 Likes
oheil
September 26, 2022, 4:32pm
7
This seems to depend on the system. I tried out with WSL2 and this doesnât work there. I had to use the triple escape version
run(`bash -c "echo \\\${PATH}"`)
here also.
On windows, with julia running in a bash,
julia> run(`bash -c "echo \\\${PATH}"`)
${PATH}
â[0mProcess(`â[4mbashâ[24m â[4m-câ[24m â[4m'echo \${PATH}'â[24m`, ProcessExited(0))
julia>
So, no, this didnât work.
Palli
September 26, 2022, 5:52pm
9
That didnât even work on (my Mint) Linux. This works for me:
julia> run(`bash -c "echo \${PATH}"`)
Iâm confused why \\ would be needed in WSL2, or why you tried that way. It doesnât get me the actual path, only
julia> run(`bash -c "echo \\\${PATH}"`)
${PATH}
Process(`bash -c 'echo \${PATH}'`, ProcessExited(0))
I think the point of (bash in) WSL2 is that whatever you do works the same as in Linux, including the default (bash) shell you would run Julia under. Iâm curious is anyone here running bash in Windows but not under WSL2? I mean is that possible? Then using Windows binary of Julia, not Linux binary of Julia.
You can interpolate the dict-key access directly too:
run(`echo $(ENV["PATH"])`)
1 Like
oheil
September 26, 2022, 6:47pm
11
I just have to confirm your finding:
Native Debian bash:
julia> run(`bash -c "echo \\\${PATH}"`)
${PATH}
Process(`bash -c 'echo \${PATH}'`, ProcessExited(0))
julia> run(`bash -c "echo \${PATH}"`)
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
Process(`bash -c 'echo ${PATH}'`, ProcessExited(0))
WSL2 (Debian) bash, running native Windows Julia from path
/mnt/c/Users/Oli/AppData/Local/Programs/Julia-1.7.2/bin/julia.exe :
julia> run(`bash -c "echo \\\${PATH}"`)
/usr/local/sbin:/usr/local/bin:...
Process(`bash -c 'echo \${PATH}'`, ProcessExited(0))
julia> run(`bash -c "echo \${PATH}"`)
/bin/bash: -c: line 1: syntax error near unexpected token `('
/bin/bash: -c: line 1: `echo /usr/local/sbin:/usr/local/bin:...:/mnt/c/Program Files (x86)/Common Files/Oracle/Java/javapath: ...'
ERROR: failed process: Process(`bash -c 'echo ${PATH}'`, ProcessExited(2)) [2]
Stacktrace:
[1] pipeline_error
@ .\process.jl:531 [inlined]
[2] run(::Cmd; wait::Bool)
@ Base .\process.jl:446
[3] run(::Cmd)
@ Base .\process.jl:444
[4] top-level scope
@ REPL[2]:1
Itâs always more complicated as it seems
1 Like
What about WSL2 running Linux julia?
What happens if youâre running windows inside a Linux VM which is a guest of a Windows bare metal
My question is about WSL2 running inside Windows 10, running inside Linux VM, hosted by Windows Server bare metal. Better?
Hopefully thereâs a fixed point attractor for iterationâŚ
1 Like
This sort of confusion is precisely the reason why using system-dependent shell commands is wrong and you really donât want to do it for portability.
1 Like
OK, but when I know I have a Linux bash, taking advantage of all those powerful shell commands is a natural choice.
oheil
September 27, 2022, 9:00am
18
Is there still something I should try out?
oheil
September 27, 2022, 10:10am
19
Downloaded Generic Linux on x86 inside WSL2 and checked:
julia> run(`bash -c "echo \\\${PATH}"`)
${PATH}
Process(`bash -c 'echo \${PATH}'`, ProcessExited(0))
julia> run(`bash -c "echo \${PATH}"`)
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:...
Process(`bash -c 'echo ${PATH}'`, ProcessExited(0))
Lesson learned:
Donât use native Windows Julia inside a WSL2 Linux!
2 Likes