Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

save and restore shell variables

I have two shell scripts that I'd like to invoke from a C program. I would like shell variables set in the first script to be visible in the second. Here's what it would look like:

a.sh:

var=blah
<save vars>

b.sh:

<restore vars>
echo $var

The best I've come up with so far is a variant on "set > /tmp/vars" to save the variables and "eval $(cat /tmp/vars)" to restore them. The "eval" chokes when it tries to restore a read-only variable, so I need to grep those out. A list of these variables is available via "declare -r". But there are some vars which don't show up in this list, yet still can't be set in eval, e.g. BASH_ARGC. So I need to grep those out, too.

At this point, my solution feels very brittle and error-prone, and I'm not sure how portable it is. Is there a better way to do this?

like image 947
danvk Avatar asked Jul 11 '10 17:07

danvk


2 Answers

One way to avoid setting problematic variables is by storing only those which have changed during the execution of each script. For example,

a.sh:

set > /tmp/pre
foo=bar
set > /tmp/post
grep -v -F -f/tmp/pre /tmp/post > /tmp/vars

b.sh:

eval $(cat /tmp/vars)
echo $foo

/tmp/vars contains this:

PIPESTATUS=([0]="0")
_=
foo=bar

Evidently evaling the first two lines has no adverse effect.

like image 106
danvk Avatar answered Oct 22 '22 19:10

danvk


If you can use a common prefix on your variable names, here is one way to do it:

# save the variables
yourprefix_width=1200
yourprefix_height=2150
yourprefix_length=1975
yourprefix_material=gravel
yourprefix_customer_array=("Acme Plumbing" "123 Main" "Anytown")
declare -p $(echo ${!yourprefix@}) > varfile

# load the variables
while read -r line
do
    if [[ $line == declare\ * ]]
    then
        eval "$line"
    fi
done < varfile

Of course, your prefix will be shorter. You could do further validation upon loading the variables to make sure that the variable names conform to your naming scheme.

The advantage of using declare is that it is more secure than just using eval by itself.

If you need to, you can filter out variables that are marked as readonly or select variables that are marked for export.

Other commands of interest (some may vary by Bash version):

  • export - without arguments, lists all exported variables using a declare format
  • declare -px - same as the previous command
  • declare -pr - lists readonly variables
like image 42
Dennis Williamson Avatar answered Oct 22 '22 18:10

Dennis Williamson