Suppose I have

export MY_VAR=0

in ~/.bashrc.

I have an opened gnome terminal, and in this terminal, I change $MY_VAR value to 200. So, if I do

echo $MY_VAR

in this terminal, 200 is shown.

Now, I opened another tab in my gnome terminal, and do

echo $MY_VAR

...and instead of 200, I have 0.

What should I do to persist the 200 value when a terminal modifies an environment variable, making this modification (setting to 200) available to all subsequent sub shells and such? Is this possible?

  • Can't you just use a cron job to run a .profile script with all your exports of your ENV variable every minute or something? It's not like it's computationally expensive...
    – Benjamin
    Apr 18, 2021 at 10:34
  • Environment variables work exactly as the user in the question describes them. The only misconception here is that the second terminal is "a subsequent terminal" in terms of the propagation of environment variables. Had it been started from the command line in the first terminal, it would have worked (but the second shell would reset it to 0 again due to running the .bashrc file, but that would have been easy to fix with a conditional).
    – Kusalananda
    Apr 18, 2021 at 16:32

5 Answers 5


A copy of the environment propagates to sub-shells, so this works:

$ export MY_VAR=200
$ bash
$ echo $MY_VAR

but since it's a copy, you can't get that value up to the parent shell — not by changing the environment, at least.

It sounds like you actually want to go a step further, which is to make something which acts like a global variable, shared by "sibling" shells initiated separately from the parent — like your new tab in Gnome Terminal.

Mostly, the answer is "you can't, because environment variables don't work that way". However, there's another answer, which is, well, you can always hack something up. One approach would be to write the value of the variable to a file, like ~/.myvar, and then include that in ~/.bashrc. Then, each new shell will start with the value read from that file.

You could go a step further — make ~/.myvar be in the format MYVAR=200, and then set PROMPT_COMMAND=source ~/.myvar, which would cause the value to be re-read every time you get a new prompt. It's still not quite a shared global variable, but it's starting to act like it. It won't activate until a prompt comes back, though, which depending on what you're trying to do could be a serious limitation.

And then, of course, the next thing is to automatically write changes to ~/.myvar. That gets a little more complicated, and I'm going to stop at this point, because really, environment variables were not meant to be an inter-shell communication mechanism, and it's better to just find another way to do it.

  • 11
    I can hear the shell squealing under the torture
    – user591
    Feb 28, 2011 at 18:58
  • 2
    Well, let's step back a bit. Why do you want a global variable?
    – mattdm
    Feb 28, 2011 at 19:12
  • 1
    @mattdm: I have some "bureaucracies" that I have to obey. One of them is a bunch of codes I need to commit along with a comment. These codes are, now, in a folder hierarchy (home/user/projects/projectcode/code1/code2). I made a function that extracts code1 and code2 to env vars (so when I need to do an activity, I just call the function inside the dir with the codes), and them, when commiting, I use vim and there are some functions that read these vars and put in a comment automatically. I think using files for that can be a solution. Feb 28, 2011 at 20:24
  • 1
    It would be really nice if somebody made a program that, if you add it to run in your ~/.bashrc file, you can truly set system-wide variables. You would set one like syswidevar MYVAR=200, and ANY shell - new or old - can access $MYVAR and see the current value. The value could be stored in memory. I unfortunately lack the programming skills to make something like this.
    – leetbacoon
    Jan 26, 2020 at 17:01
  • 1
    @leetbacoon That really can't work without major changes to how environment variables work, as explained above.
    – mattdm
    Jan 26, 2020 at 19:30

Suppose I have export MY_VAR=0 in ~/.bashrc.

That's your mistake right there. You should define your environment variables in ~/.profile, which is read when you log in. ~/.bashrc is read each time you start a shell; when you start the inner shell, it overrides MY_VAR. If you hadn't done that, your environment variable would propagate downwards.

For more information on ~/.bashrc vs ~/.profile, see my previous posts on this topic.

Note that upward propagation (getting a modified value from the subshell automatically reflected in the parent shell) is not possible, full stop.


Fish shell can do this with:

set -U MY_VAR 0

(see http://fishshell.com/docs/current/commands.html#set)

To execute a fish command from another shell you can run fish -c, e.g. :

fish -c "set -u MY_VAR 0"

Don't use environment variables at all. Use files.

To prevent processes from stepping on each other when updating/reading the file, use lockfiles and small front-end updater scripts whose purpose is just updating a file with $1 if it's not locked. Lockfiles are implemented by basically checking if a specific file exists (/var/run/yourscript.lck) and if it does, wait for the file to disappear for a while, and fail if it doesn't. Also you must delete the lockfile when done updating the file.

Be prepared to handle a situation where a script can't update a file because the file is busy.

  • 8
    A trick: use directories instead of files for locking, because mkdir works as an atomic test-and-create.
    – mattdm
    Feb 28, 2011 at 20:53
  • 1
    If you guys want to talk about locking, then you might as well be using flock(2) Apr 12, 2013 at 23:20
  • @mattdm I found that a symlink ln -s dummy lockfile (even if broken) may work too as it will fail if the symlink already exists. I wonder some way to test if that is truly 100% secure. Aug 18, 2013 at 20:26
  • If you use files, what if the computer is forcefully and unexpectedly powered off? Upon reboot your script may still think something is locked if a file still exists
    – leetbacoon
    Jan 26, 2020 at 17:37
  • Add a line in /etc/rc.local or other script that starts on reboot to delete the lockfile.
    – LawrenceC
    Jan 26, 2020 at 17:40

When I just have googled this question up, I was trying to solve the problem of updating state (i.e. shell variables) from out of subshells. So that one could assign variables, say, inside of a pipeline – and the assignment would be transparently visible to the parent.

Off course, this is not possible in a simple way because individual parts of a pipeline are executed in subshells, which are fork'ed from the parent shell and therefore have memory which is copy-on-write view on the parent's memory. However, I supposed that slim and transparent solution could be possible based on "shared memory" sort of IPCs.

And I have even found an implementation of exactly this design... but it's in Perl.

Adding this answer anyway as a possible solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.