Lets say I have a shell / bash script named test.sh
with:
#!/bin/bash
TESTVARIABLE=hellohelloheloo
./test2.sh
My test2.sh
looks like this:
#!/bin/bash
echo ${TESTVARIABLE}
This does not work. I do not want to pass all variables as parameters since imho this is overkill.
Is there a different way?
Fatal Error gave a straightforward possibility: source your second script! if you're worried that this second script may alter some of your precious variables, you can always source it in a subshell:
The parentheses will make the source happen in a subshell, so that the parent shell will not see the modifications
test2.sh
could perform.There's another possibility that should definitely be referenced here: use
set -a
.From the POSIX
set
reference:From the Bash Manual:
So in your case:
Observe that the specs only specify that with
set -a
the variable is marked for export. That is:will echo
c
and not an empty line norb
(that is,set +a
doesn't unmark for export, nor does it “save” the value of the assignment only for the exported environment). This is, of course, the most natural behavior.Conclusion: using
set -a
/set +a
can be less tedious than exporting manually all the variables. It is superior to sourcing the second script, as it will work for any command, not only the ones written in the same shell language.There's actually an easier way than exporting and unsetting or sourcing again (at least in bash, as long as you're ok with passing the environment variables manually):
let a.sh be
and b.sh be
Observed output is
The magic lies in the last line of
a.sh
, whereMessage
, for only the duration of the invocation of./b.sh
, is set to the value ofsecret
froma.sh
. Basically, it's a little like named parameters/arguments. More than that, though, it even works for variables like$DISPLAY
, which controls which X Server an application starts in.Remember, the length of the list of environment variables is not infinite. On my system with a relatively vanilla kernel,
xargs --show-limits
tells me the maximum size of the arguments buffer is 2094486 bytes. Theoretically, you're using shell scripts wrong if your data is any larger than that (pipes, anyone?)Another option is using
eval
. This is only suitable if the strings are trusted. The first script can echo the variable assignments:echo "VAR=myvalue"
Then:
eval $(./first.sh) ./second.sh
This approach is of particular interest when the second script you want to set environment variables for is not in bash and you also don't want to
export
the variables, perhaps because they are sensitive and you don't want them to persist.In Bash if you export the variable within a subshell, using parentheses as shown, you avoid leaking the exported variables:
The advantage here is that after you run the script from the command line, you won't see a $TESTVARIABLE leaked into your environment:
You have basically two options:
export TESTVARIABLE
) before executing the 2nd script.. test2.sh
and it will run in the same shell. This would let you share more complex variables like arrays easily, but also means that the other script could modify variables in the source shell.UPDATE:
To use
export
to set an environment variable, you can either use an existing variable:This ought to work in both
bash
andsh
.bash
also allows it to be combined like so:This also works in my
sh
(which happens to bebash
, you can useecho $SHELL
to check). But I don't believe that that's guaranteed to work in allsh
, so best to play it safe and separate them.Any variable you export in this way will be visible in scripts you execute, for example:
a.sh:
b.sh:
Then:
The fact that these are both shell scripts is also just incidental. Environment variables can be passed to any process you execute, for example if we used python instead it might look like:
a.sh:
b.py:
Sourcing:
Instead we could source like this:
a.sh:
b.sh:
Then:
This more or less "imports" the contents of
b.sh
directly and executes it in the same shell. Notice that we didn't have to export the variable to access it. This implicitly shares all the variables you have, as well as allows the other script to add/delete/modify variables in the shell. Of course, in this model both your scripts should be the same language (sh
orbash
). To give an example how we could pass messages back and forth:a.sh:
b.sh:
Then:
This works equally well in
bash
. It also makes it easy to share more complex data which you could not express as an environment variable (at least without some heavy lifting on your part), like arrays or associative arrays.Adding to the answer of Fatal Error, There is one more way to pass the variables to another shell script.
The above suggested solution have some drawbacks:
using Export
: It will cause the variable to be present out of their scope which is not a good design practice.using Source
: It may cause name collisions or accidental overwriting of a predefined variable in some other shell script file which have sourced another file.There is another simple solution avaiable for us to use. Considering the example posted by you,
test.sh
test2.sh
output
Also it is important to note that
""
are necessary if we pass multiword strings. Taking one more examplemaster.sh
slave1.sh
slave2.sh
output
It happens because of the reasons aptly described in this link