2010-07-11 150 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 $?