Reputation: 93
I am trying to export a variable from one script and use it in another script but this variable is not being exported what might be the problem
Consider this as script1
#!/bin/sh
export x=19
exit 0
Consider this as script2
#!/bin/sh
echo "x="${x}
exit 0
i am executing them as two independent scripts like
desktop:~/Desktop/Trail_Programs$ sh script1.sh
desktop:~/Desktop/Trail_Programs$ sh script2.sh
and output is
desktop:~/Desktop/Trail_Programs$ sh script2.sh
x=
Upvotes: 3
Views: 8870
Reputation: 440556
David C. Rankin's helpful answer explains why your code didn't work.
Note:
The following solution should only be used if modifying the scripts you work with is not an option (the solution may also be of interest if you want to learn about sourcing and ad-hoc environment variables).
Otherwise, see the solutions discussed at the bottom.
To solve your problem, you can try the following:
x=$(trap 'printf %s "$x"' EXIT; . script1.sh >/dev/null) sh script2.sh
Note, however, that:
script1.sh
will - of necessity - be executed by your current shell, which may or may not be sh
.script1.sh
's stdout output is suppressed, because it must be ensured that printf %s "$x"
is the only stdout output produced by the subshell inside the command substitution ($(...)
).. script1.sh
sources the script inside the subshell, which means that the subshell executes script1.sh
directly in its own environment and therefore sees the script's variables after executing it (which means it would see $x
even if it weren't exported).
trap 'printf %s "$x"' EXIT
sets up an exit trap; i.e., code that executes when the subshell exits, in this case printf %s "$x"
, which simply outputs the value of the variable of interest.
Note that this approach is necessary to ensure that the value of $x
is printed even if script1.sh
terminates due to an exit
statement; since script1.sh
is being sourced by the subshell, exit
exits the entire subshell.
x=$(...)
captures that value, and, by being prepended to command sh script2.sh
, effectively makes the resulting $x
an environment variable that script2.sh
then sees.
It's generally problematic to source scripts that weren't designed to be sourced:
exit
, they will exit the calling shell too.If the scripts involved cannot be modified for some reason, the solution above is the best choice, because it bypasses these problems, albeit with some limitations.
More robust, generic solutions (modification of the scripts required):
Having the script that sets the environment variable(s) of interest itself invoke the other script is the right solution, as shown in David's answer.
If scripts do need to run as peers, values need to be passed via files: have the script that sets the variable(s) of interest write their values to a (temporary) file and have the other script read that file:
script1.sh
:
#!/bin/sh
export x=19
# Write to temp. file named for the *parent* process ID.
# Since both script calls will have the same parent process, this
# allows you to avoid a static filename subject to name collisions.
printf %s "$x" > /tmp/x.$PPID
script2.sh
:
#!/bin/sh
# Read the value of $x from the temp. file, then delete the file.
x=$(cat /tmp/x.$PPID) && rm /tmp/x.$PPID
echo "x=${x}"
Upvotes: 1
Reputation: 84652
Remember a script may NEVER affect its parent's environment. NEVER means NEVER. So following the rule:
#!/bin/bash
export x=19
exit 0
has NO effect on the environment and does not set x=anything
there. The export
would only affect the environment of subshells created from within that script. For example take your script, call it exp.sh
:
#!/bin/bash
export x=19
./script2.sh
exit 0
and in script2.sh
you have:
echo "x = $x"
Then, and only then, will you get:
$ bash exp.sh
x = 19
That's just the rule...
Upvotes: 4
Reputation: 21965
Suppose you have file tobeincluded1
with following content
#this file tobeincluded1 will be included in master
x=16
and file tobeincluded2
with following content
#this file tobeincluded2 will be included in master
y=21
you can include the above files in your script using either .
or source
like below:
#!/bin/bash
. ./tobeincluded1 #using the . to include a file
source ./tobeincluded2 #using the source command to include a file
echo "x : $x"
echo "y : $y"
Upvotes: 0
Reputation: 42137
source
script1.sh
from script2.sh
.
At the start of script2.sh
(after the shebang), add:
source /path/to/script1.sh
Upvotes: 2