27

a.sh

#! /bin/sh
export x=/usr/local

we can do source ./a in command-line. But I need to do the export through shell script.

b.sh

#! /bin/sh
. ~/a.sh

no error... but $x in command-line will show nothing. So it didn't get export.

Any idea how to make it work?


a.sh

#! /bin/sh
export x=/usr/local
-----------
admin@client: ./a.sh
admin@client: echo $x

admin@client:  <insert ....>
2
  • related: superuser.com/questions/176783/… Commented Jul 26, 2014 at 20:21
  • If it is an option you can instead have the content of a.sh in a bash function (e.g in .bash_profile or something else for other shells) Commented Jun 30, 2022 at 18:40

6 Answers 6

122

You can put export statements in a shell script and then use the 'source' command to execute it in the current process:

source a.sh
Sign up to request clarification or add additional context in comments.

4 Comments

This answer should have a tick
This answer should have a tick +1
Continuing the train. This should be the correct answer ;)
Need a community over-ride for accepted answer hehe
31

You can't do an export through a shell script, because a shell script runs in a child shell process, and only children of the child shell would inherit the export.

The reason for using source is to have the current shell execute the commands

It's very common to place export commands in a file such as .bashrc which a bash will source on startup (or similar files for other shells)

Another idea is that you could create a shell script which generates an export command as it's output:

shell$ cat > script.sh
#!/bin/sh
echo export foo=bar
^D
chmod u+x script.sh

And then have the current shell execute that output

shell$ `./script.sh`

shell$ echo $foo
bar

shell$ /bin/sh
$ echo $foo
bar

(note above that the invocation of the script is surrounded by backticks, to cause the shell to execute the output of the script)

4 Comments

Type ctrl-D and then return to finish writing the file you are creating with cat
Thanks. I updated my post. I tried, but when I printed out it jsut gave me an empty line. Nothing happened?
I'm not sure exactly what you did, but it's not what I did. Note the backticks around the execution of the shell script, and that the script echos an export command rather than executing one itself.
Yes, though I'm not sure if it's that useful.
6

Answering my own question here, using the answers above: if I have more than one related variable to export which use the same value as part of each export, I can do this:

#!/bin/bash
export TEST_EXPORT=$1
export TEST_EXPORT_2=$1_2
export TEST_EXPORT_TWICE=$1_$1

and save as e.g. ~/Desktop/TEST_EXPORTING

and finally $chmod +x ~/Desktop/TEST_EXPORTING

--

After that, running it with source ~/Desktop/TEST_EXPORTING bob

and then checking with export | grep bob should show what you expect.

2 Comments

Can't tell you how happy I am to find this answer after banging my head against my table for over 4h.... Now I can finally clean up the blood and put a band aid on my forehead hahaha
source only needs read access, you only need chmod +x for files that you actually want to execute.
3

Exporting a variable into the environment only makes that variable visible to child processes. There is no way for a child to modify the environment of its parent.

Comments

1

Another way you can do it (to steal/expound upon the idea above), is to put the script in ~/bin and make sure ~/bin is in your PATH. Then you can access your variable globally. This is just an example I use to compile my Go source code which needs the GOPATH variable to point to the current directory (assuming you're in the directory you need to compile your source code from):

From ~/bin/GOPATH:

#!/bin/bash

echo declare -x GOPATH=$(pwd) 

Then you just do:

#> $(GOPATH)

So you can now use $(GOPATH) from within your other scripts too, such as custom build scripts which can automatically invoke this variable and declare it on the fly thanks to $(pwd).

Comments

0

script1.sh

shell_ppid=$PPID
shell_epoch=$(grep se.exec_start "/proc/${shell_ppid}/sched" | sed 's/[[:space:]]//g' | cut -f2 -d: | cut -f1 -d.)
now_epoch=$(($(date +%s%N)/1000000))
shell_start=$(( (now_epoch - shell_epoch)/1000 ))
env_md5=$(md5sum <<<"${shell_ppid}-${shell_start}"| sed 's/[[:space:]]//g' | cut -f1 -d-)
tmp_dir="/tmp/ToD-env-${env_md5}"
mkdir -p "${tmp_dir}"
ENV_PROPS="${tmp_dir}/.env"
echo "FOO=BAR" > "${ENV_PROPS}"

script2.sh

shell_ppid=$PPID
shell_epoch=$(grep se.exec_start "/proc/${shell_ppid}/sched" | sed 's/[[:space:]]//g' | cut -f2 -d: | cut -f1 -d.)
now_epoch=$(($(date +%s%N)/1000000))
shell_start=$(( (now_epoch - shell_epoch)/1000 ))
env_md5=$(md5sum <<<"${shell_ppid}-${shell_start}"| sed 's/[[:space:]]//g' | cut -f1 -d-)
tmp_dir="/tmp/ToD-env-${env_md5}"
mkdir -p "${tmp_dir}"
ENV_PROPS="${tmp_dir}/.env"
source "${ENV_PROPS}"
echo $FOO
./script1.sh
./script2.sh
BAR

It persists for the scripts run in the same parent shell, and it prevents collisions.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.