Using Julia to set env variables

I’d like to set environment variables in the enclosing shell from a Julia script. I’d have thought I could do

run(`export TESTVAR=varname`)

but I got the following very unexpected error

ERROR: IOError: could not spawn `export TESTVAR=varname`: no such file or directory (ENOENT)
Stacktrace:
 [1] _spawn_primitive(::String, ::Cmd, ::Array{Any,1}) at ./process.jl:400
 [2] setup_stdios(::getfield(Base, Symbol("##505#506")){Cmd}, ::Array{Any,1}) at ./process.jl:413
 [3] _spawn at ./process.jl:412 [inlined]
 [4] #run#515(::Bool, ::Function, ::Cmd) at ./process.jl:725
 [5] run(::Cmd) at ./process.jl:724
 [6] top-level scope at none:0

Anyone know what’s going on here?

I think this arises from the fact that export is not a external command (i.e., a binary resting in some path, if you do which export you will see that the command which does not find the export binary) but an internal builtin command of the shell (if you do man bash, or man your-shell-here, you will see it described as a builtin command).

I am not sure how I would solve that, but maybe doing something as:

run(`bash -e """
export TESTVAR=varname
<the rest of your code there?>
"""`)

But probably the best would be use Julia specific commands for dealing with environment variables: Environment Variables · The Julia Language

Is your goal to be able to do something like this?

$ echo $FOO 
<nothing here>
$ julia my_script.jl

$ echo $FOO
<somehow FOO is now set>

If so, then I believe that’s impossible, not just for Julia but for any program. Every program (like Julia) inherits a copy of its parent’s environment variables, so there’s no way to modify environment variables in the parent shell.

3 Likes

I suppose that makes sense. If that’s the case, I probably need to reconsider what I’m doing, and make everything work via ENV only from within Julia.

Depending on what you’re trying to achieve, e.g. if Julia is useful to perform a lot of data treatment which ultimately produce a single (but potentially very complex) value for an environment variable, then something like this might be useful:

> echo $FOO

> cat foo.jl
println("my very complex result")

> export FOO=$(julia foo.jl)

> echo $FOO
my very complex result

In another, more complex variant, you can have julia output a snippet of shell that sets the correct environment variables (AFAIK this is what lmod does, for example)

> echo $FOO

> cat foo.jl
println("FOO=\"my very complex result\"")

> eval $(julia foo.jl)

> echo $FOO
my very complex result

I wouldn’t recommand this last variant unless you really know what you’re doing: you’ll have to make sure that evaluating the output of your julia script in the shell never does anything stupid.

In any case, if you can re-design your solution so that everything happens in Julia (or in subprocesses of the Julia process), then it would be much better.

I don’t know the details of your problem, but an environment variable could point to a file, which you could use to interchange data.

Yeah, I suppose my original idea was a bad one. I wanted to have a single Julia script that could do a whole bunch of things to set up “an environment”. Since this would largely be just to run more Julia code anyway, I probably just need a somewhat more sophisticated Julia command line program than I had originally envisioned.