2010-07-11 152 views
6

我有两个我想从C程序中调用的shell脚本。我希望在第一个脚本中设置的shell变量在第二个脚本中可见。下面是它会是什么样子:保存和恢复shell变量

a.sh:

var=blah 
<save vars> 

b.sh:

<restore vars> 
echo $var 

我想出迄今最好的是一个变体的“设置>/tmp/vars“来保存变量和”eval $(cat/tmp/vars)“来恢复它们。当它试图恢复一个只读变量时,“eval”扼流器,所以我需要grep那些。这些变量的列表可以通过“declare -r”获得。但是有一些变化没有出现在这个列表中,但仍然不能在eval中设置,例如, BASH_ARGC。所以我也需要把这些弄清楚。

在这一点上,我的解决方案感觉非常脆弱和容易出错,我不确定它是多么便携。有一个更好的方法吗?

回答

0

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

不知道,如果它接受的教条,而是:

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

的otherscript将打印到XXXX的ENV ...

更新:

还要注意:

man execle 

关于如何为C中的另一个系统调用设置环境变量,如果需要执行那。和:

man getenv 

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

+0

我需要做一些工作用C a.sh和b.sh的执行之间,所以这是不可能的,以B键。请注意,我对shell变量感兴趣,而不是环境变量。 – danvk 2010-07-11 17:38:03

+0

啊,对不起! – eruciform 2010-07-11 18:41:36

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 ${[email protected]}) > 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 - 列出只读变量
+0

这两个脚本是用户提供的,所以需要一个通用的前缀会有点尴尬。 另一方面,我可以检查每个脚本已修改的变量。将这个想法放在答案中,以便我可以格式化... – danvk 2010-07-11 18:00:50

4

避免设置有问题的变量的一种方法是通过st或者只是那些在每个脚本执行期间已经改变的那些。例如,

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 /瓦尔包含此:

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

前两行显然evaling具有没有不良影响。

+1

'set'将包含函数定义,'declare -p'不会('declare -f'将会)。请注意''eval'的[安全风险](http://mywiki.wooledge.org/BashFAQ/048),其中包含未验证或未受保护的(例如'declare')输入。 – 2010-07-11 18:29:51

0

保存和恢复shell状态的替代方法是使C程序和shell程序并行工作:C程序启动运行a.sh的shell程序,然后通知C程序(可能传递一些信息从执行a.sh得知),并且当C程序准备好更多时,它会通知shell程序运行b.sh。壳程序应该是这样的:

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

而C程序的一般结构是:

  • 设置两对管,一个用于C->壳,一个用于壳 - >ç
  • 叉,执行的是壳包装
  • 读出来自收集在壳 - >ç管
  • 多个处理
  • 写入信息对于B关于C->壳管
  • 等待子进程结束
0

论点我去寻找类似的东西,可能就是找不到它,所以我做了以下两个脚本。首先,说shellstate,然后可能至少set -iset -o emacsreset_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 "[email protected]" 
exit $?