Export Variables in Bash

by mike on November 29, 2010

You may need to export variables in some circumstances in order to use them in the child process.   The export command places the variable in the environment.  The environment, which is the list of name-value pairs like PATH, is inherited from the parent process.  The export command allows the child process to modify the environment of the child environment only.

Locality of Variables
Variables are local to the process where they were declared.  See Declaring Variables for more context that helps define this blog post.

The export command with the “-p” option will show the  current variables of the environment.

export -p
declare -x G_BROKEN_FILENAMES=”1″
declare -x HISTSIZE=”1000″
declare -x HOME=”/root”
declare -x HOSTNAME=”mail.example.com”
declare -x INPUTRC=”/etc/inputrc”
declare -x LANG=”en_US.UTF-8″
declare -x LESSOPEN=”|/usr/bin/lesspipe.sh %s”
declare -x LOGNAME=”root”
declare -x LS_COLORS=”no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=00;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;31:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00;35:*.xpm=00;35:*.png=00;35:*.tif=00;35:”
declare -x MAIL=”/var/spool/mail/root”
declare -x OLDPWD=”/root”
declare -x PATH=”/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin”
declare -x PWD=”/root/scripts”
declare -x SHELL=”/bin/bash”
declare -x SHLVL=”1″
declare -x SSH_CLIENT=”192.168.5.103 44268 22″
declare -x SSH_CONNECTION=”192.168.5.103 44268 192.168.5.212 22″
declare -x SSH_TTY=”/dev/pts/0″
declare -x TERM=”xterm”
declare -x USER=”root”

In this example the $TIME variable has not been declared so export will be used to place it in the environment.

#!bin/bash
ONLINE=$(who)
echo “These people are online: ” $ONLINE
USERS=$(who | awk {‘print $1′})
echo “These users are logged in: ” $USERS
IP=`who | awk {‘print $5′}`
echo “Logged in from this IP Address: ” $IP
echo “The current time is: ” $TIME

Now declare the variable from the command line.  You can see the variable declared and that when you echo the variable it works correctly.

TIME=$(who | grep “pts/1” | awk {‘print $3,$4′})
echo $TIME

2010-08-10 00:20

If this returns an empty like check the pts that you are logged in on and change to the pts, in this example it would be pts/0.
who
z4       tty7         2010-12-01 03:27 (:0)
z4       pts/0        2010-12-01 04:08 (:0.0)

However, when you run the script you created using the $TIME variable it does not work and still returns an empty string.

The current time is:

The reason for this is that when you run the script from the interactive shell a new shell is spawned, and the new shell does not have the variable declared, only your current shell has that variable declared.  If you export that TIME variable it will be available to all shells.

export TIME

Now when you run the script it works as expected.  If you look at your environment you can see this variable is a part of the user environment currently.

env
TIME=2010-08-10 00:20

If you remove that variable you will see it disappears and the script fails as before.

unset TIME

{ 8 comments }

Anonymous Coward November 30, 2010 at 11:57 am

“The export command places the variable in the environment”
You’ve got your basics wrong, man.
“X=2″ will place variable in environment just fine.
Environment (list of name-value pairs) is inherited from parent by child. It’s one way communication (parent->child), and only those values that parent EXPORTed are inherited, others are not. So if you want the child to see and use a variable, parent must export it. (If child modifies this exported variable, parent will NOT see the change. That’s because environment is inherited by copying value-name pairs, and each copy is unique).

“The export command allows the child process to modify the environment.”
Wrong. Child can modify its environment as it sees fit, but it cannot change parent environment at all. If child exports variable, that variable will be visible to child itself and to its own children (if any). But in no way can child modify parent environment!

So export is only used when you are concerned about children’s environment.

mike November 30, 2010 at 12:28 pm

Thanks for the reply. I have clarified the post as it is often difficult to bring context into a blog post. I can see where it was easy to read this post alone and not understand the context. One of the great values of putting text online is that people view it from a different perspective and it helps to clarify text. It is easy as a writer to mean one thing but it is misinterpreted because of the inability to write as clearly as you would like. Anyway, I have made some changes to clarify, and made a link to the context in which I was writing from to help read the post.

zman58 November 30, 2010 at 4:07 pm

Just a bit confusing Mike, but sparked my interest.
Here is an slight alternative for demonstration purposes.
Create script1 and script 2 as follows. Make sure both are set to executable (e.g. “chmod 744 script1″).
Invoke script2, which exports $WHEN, then calls script1. Test difference by commenting out/in the “export” statement in script2 just before you invoke it. Script1 will only see $WHEN if script 1 exports it to the environment for use by the child process invoked to run script1.

script1:
———-
#!/bin/bash
# write this text to executable “script1″
USERS=$(who | awk {‘print $1′})
echo These users are logged in: $USERS
SESS=`who | awk {‘print $2′}`
echo Logged in from this session: $SESS
echo Logged in at this date time: $WHEN
———-

script2:
——–
#!/bin/bash
# write this text to executable “script2″
WHEN=`who | awk {‘print $3,$4′}`
echo $WHEN
export WHEN
./script1
————–

PS, You may have to fix the encoding on the accents characters.
Hope that helps the readers.

scribe63 November 30, 2010 at 7:21 pm

For the record:
I do appreciate this web, and have been following each tutorial. It sure is helping me get my scripting on.
In this tutorial like you said, everything in the script works, except for,
TIME=$(who | grep “pts/1” | awk {‘print $3,$4′})
echo $TIME

But it is giving me a blank line in gnome terminal also.
TIME=$(who | grep “pts/1” | awk {‘print $3,$4′})
echo $TIME

I am trying it on Ubuntu 10.04 32 and 64 bit, what could i be doing wrong?

mike December 1, 2010 at 11:02 am

I added the explanation for this in the post, it is determined by the pts, so just do a who to check first. Thanks for the comment.

dutchkind December 1, 2010 at 7:04 am

Interesting post!
About:
TIME=$(who | grep “pts/1” | awk {‘print $3,$4′})
echo $TIME

If I try only “who” in a konsole, I only get pts/3 and pts/4 being used, so it can depend on disto, in my case opensuse. So for me it could be:
TIME=$(who | grep “pts/3” | awk {‘print $3,$4′})
echo $TIME

Another note: At first it also didn’t work because the single and double quotes are copied wrong. Just delete them from the commandline and replace them with the correct ones by typing them solves that problem.

scribe63 December 1, 2010 at 9:44 pm

Thanks for the replies guys, they have been really helpful, and i do appreciate it.

@mike
I payed closer attention to the results of the “who” command and realized what a difference it makes. I am surely getting a better understanding of the “Terminal” concepts also.
On one computer i was “tty7″ on the other “pts/2″

@dutchkind
Thanks for pointing the issues with the double quotes from copying.
I had initially fixed errors for the single quotes that “awk” complained about, but sure didn’t notice the difference with the double quotes when typed as opposed to when copied.

@mike again
Initially the “export TIME” option still was not working in the script.
But after re-typing all double quotes, “echo $TIME” now works on both computers without “export TIME” option within the script.

#export TIME
#TIME=$(who | grep “pts/0″ | awk {‘print $3,$4′})
TIME=$(who | grep “tty7″ | awk {‘print $3,$4′})
echo “The current time is: ” $TIME

sh export-var.sh
These users are online: jawara tty7 2010-12-01 10:49 (:0)
These users are logged in: jawara
Logged in from this IP Address: (:0)
The current time is: 2010-12-01 10:49

I guess it is safe to assume that the displayed “echo $TIME” is just your fixed log in time, as oppose to the current time when the script is run.

PEACE

christian December 2, 2010 at 7:00 am

when you’re programming more complex scripts and not having all the code in one big file but split into severals, it tourned out to be good idea to set LANG=C and export this to the environment of all childs. this is specifically true if you’re not living in the US such as germany and distributing your code to others. standard output of commnds tends to be dramatically different in other languages.

this leads to the second question: how to parse enviroment in such child scripts? see my solution:

REQUEST_LANGUAGE=${REQUEST_LANGUAGE:=$(source ${CONF}; echo $REQUEST_LANGUAGE)}

REQUEST_LANGUAGE=${REQUEST_LANGUAGE:=”eng”}

any better doing this? (i bed there is)

Comments on this entry are closed.

Previous post:

Next post: