保存和恢复shell变量

时间:2010-07-11 17:03:15

标签: c bash shell environment-variables

我有两个shell脚本,我想从C程序调用。我希望在第一个脚本中设置的shell变量在第二个脚本中可见。这就是它的样子:

a.sh:

var=blah
<save vars>

b.sh:

<restore vars>
echo $var

到目前为止,我提出的最好的是“set&gt; / tmp / vars”的变体来保存变量,并使用“eval $(cat / tmp / vars)”来恢复它们。当它试图恢复只读变量时,“eval”会窒息,所以我需要把它们弄出来。可以通过“declare -r”获得这些变量的列表。但是有一些vars没有出现在这个列表中,但仍然无法在eval中设置,例如BASH_ARGC。所以我也需要把它们弄出来。

此时,我的解决方案感觉非常脆弱且容易出错,而且我不确定它是多么便携。有更好的方法吗?

5 个答案:

答案 0 :(得分:4)

避免设置有问题变量的一种方法是仅存储在执行每个脚本期间已更改的变量。例如,

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包含:

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

显然评估前两行没有任何不利影响。

答案 1 :(得分:2)

如果您可以在变量名称上使用公共前缀,则可以使用以下方法:

# 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

当然,您的前缀会更短。您可以在加载变量时进行进一步验证,以确保变量名称符合您的命名方案。

使用declare的优势在于它比仅使用eval更安全。

如果需要,可以过滤掉标记为只读的变量,或者选择标记为导出的变量。

其他感兴趣的命令(有些可能因Bash版本而异):

  • export - 不带参数,使用declare格式列出所有导出的变量
  • declare -px - 与上一个命令相同
  • declare -pr - 列出只读变量

答案 2 :(得分:0)

如果a.sh可以调用b.sh,它将在导出时继续运行。或者让父母设置所需的所有值,然后调用两者。这是我能想到的最安全可靠的方法。

不确定它是否被接受为教条,但是:

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

其他文字将env打印到xxxx ...

更新

另请注意:

man execle

如果需要,可以从C中为另一个系统调用设置环境变量。和

man getenv

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

答案 3 :(得分:0)

保存和恢复shell状态的另一种方法是使C程序和shell程序并行工作:C程序启动shell程序,运行a.sh,然后通知C程序(也许通过从执行a.sh)中学到的一些信息,当C程序准备好了更多时,它告诉shell程序运行b.sh。 shell程序看起来像这样:

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

C程序的一般结构是:

  • 设置两对管道,一个用于C-> shell,另一个用于shell-> C
  • fork,exec shell wrapper
  • 读取从shell-&gt; C管道上收集的信息
  • 更多处理
  • 在C-&gt; shell管道上为b写入参数
  • 等待子进程结束

答案 4 :(得分:0)

我去寻找类似的东西,也找不到它,所以我在下面制作了两个脚本。首先,只说shellstate,然后可能至少set -iset -o emacs这个reset_shellstate不适合你。我不知道如何向bash询问它认为特殊的变量。

~/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 $?