Save and restore shell variables

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

a.sh:

var=blah <save vars> 

b.sh:

 <restore vars> echo $var 

The best I've come up with so far is the option on "set> / tmp / vars" to save the variables and "eval $ (cat / tmp / vars)" to restore them. "Eval" suffocates when it tries to restore a read-only variable, so I need to return them. A list of these variables is available through declare -r. But there are some vars that do not appear on this list, but still cannot be set to eval, for example. BASH_ARGC Therefore, I also need to pull them out.

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

+6
c bash shell environment-variables
source share
5 answers

One way to avoid problem variables is to save only those that were 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 the following:

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

Obviously, deviation from the first two lines does not have a negative effect.

+4
source share

If you can use a common prefix for variable names, here is one way to do this:

 # 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 can perform additional checks when loading variables to make sure that the variable names match your naming scheme.

The advantage of using declare is that it is safer than using eval itself.

If you need, you can filter the variables marked as readonly, or select the variables marked for export.

Other commands of interest (some may differ from the Bash version):

  • export - without arguments, lists all exported variables using declare format
  • declare -px - same as previous command
  • declare -pr - lists readonly variables
+2
source share

If it is possible for a.sh to call b.sh, it will be portable if they are exported. Or having a parent set of all the necessary values, and then call both. This is the safest and surest method that I can think of.

Not sure if he accepted the dogma, but:

 bash -c 'export foo=bar; env > xxxx' env `cat xxxx` otherscript.sh 

In othercript file env will be printed on xxxx ...

Update:

Also note:

 man execle 

About how to set environment variables for another system call from C, if you need to do this. BUT:

 man getenv 

and http://www.crasseux.com/books/ctutorial/Environment-variables.html

0
source share

An alternative to saving and restoring the state of the shell would be to run the program C and the shell in parallel: program C starts the shell program, which starts a.sh , then notifies the program C (perhaps by passing some information it learned from the execution of a.sh ), and when C program is ready for more, it tells the shell program to run b.sh The shell program will look like this:

  .  a.sh
 echo "information gleaned from a"
 arguments_for_b = $ (read -r)
 .  b.sh

And the general structure of the C program:

  • set two pairs of pipes, one for C-> shell and one for shell β†’ C
  • fork, execute shell shell
  • read information received from a on pipe shell-> C
  • more processing
  • write arguments to b in pipe C-> shell
  • wait for the completion of the child process
0
source share

I was looking for something similar and could not find it, so I made two scenarios below. To get started, just say shellstate and then at least set -i and set -o emacs , which this reset_shellstate does not do for you. I do not know how to set bash variables which, in his opinion, are special.

~/bin/reset_shellstate :

 #!/bin/bash __="$PWD/shellstate_${1#_}" trap ' declare -p >"'"$__"'" trap >>"'"$__"'" echo cd \""$PWD"\" >>"'"$__"'" # setting PWD did this already, but... echo set +abefhikmnptuvxBCEHPT >>"'"$__"'" echo set -$- >>"'"$__"'" # must be last before sed, see $s/s//2 below sed -ri '\'' $s/s//2 s,^trap --,trap, /^declare -[^ ]*r/d /^declare -[^ ]* [A-Za-z0-9_]*[^A-Za-z0-9_=]/d /^declare -[^ ]* [^= ]*_SESSION_/d /^declare -[^ ]* BASH[=_]/d /^declare -[^ ]* (DISPLAY|GROUPS|SHLVL|XAUTHORITY)=/d /^declare -[^ ]* WINDOW(ID|PATH)=/d '\'' "'"$__"'" shopt -op >>"'"$__"'" shopt -p >>"'"$__"'" declare -f >>"'"$__"'" echo "Shell state saved in '"$__"'" ' 0 unset __ 

~/bin/shellstate :

 #!/bin/bash shellstate=shellstate_${1#_} test -s $shellstate || reset_shellstate $1 shift bash --noprofile --init-file shellstate_${1#_} -is " $@ " exit $? 
0
source share

All Articles