将所有variables从一个shellcript传递给另一个?
所以可以说我有一个名为test.sh的shell脚本
有:
#!/bin/bash # TESTVARIABLE=hellohelloheloo ./test2.sh
我的test2.sh看起来像这样
#!/bin/bash # echo ${TESTVARIABLE}
这不起作用。 我不想将所有variables作为parameter passing,因为这是过度的。 有不同的方法吗?
你基本上有两个select:
- 在执行第二个脚本之前,将该variables设置为环境variables(
export TESTVARIABLE
)。 - 来源第二个脚本,即
. test2.sh
. test2.sh
,它将在同一个shell中运行。 这将使您可以轻松地共享像数组这样更复杂的variables,也意味着其他脚本可以修改源shell中的variables。
更新:
要使用export
来设置环境variables,可以使用现有的variables:
A=10 # ... export A
这应该在bash
和sh
两个工作。 bash
也允许它像这样组合:
export A=10
这也适用于我的 sh
(这恰好是bash
,你可以使用echo $SHELL
来检查)。 但我不相信这是保证一切工作,所以最好把它安全地分开。
以这种方式导出的任何variables将在您执行的脚本中可见,例如:
灰:
#!/bin/sh MESSAGE="hello" export MESSAGE ./b.sh
b.sh:
#!/bin/sh echo "The message is: $MESSAGE"
然后:
$ ./a.sh The message is: hello
这些都是shell脚本的事实也是偶然的。 环境variables可以传递给你执行的任何进程,例如,如果我们使用python,它可能看起来像这样:
灰:
#!/bin/sh MESSAGE="hello" export MESSAGE ./b.py
b.py:
#!/usr/bin/python import os print 'The message is:', os.environ['MESSAGE']
采购:
相反,我们可以这样来源:
灰:
#!/bin/sh MESSAGE="hello" . ./b.sh
b.sh:
#!/bin/sh echo "The message is: $MESSAGE"
然后:
$ ./a.sh The message is: hello
这b.sh
直接“导入” b.sh
的内容并在同一个shell中执行它。 注意,我们不必导出variables来访问它。 这隐含地共享你拥有的所有variables,并允许其他脚本在shell中添加/删除/修改variables。 当然,在这个模型中,你的脚本应该是相同的语言( sh
或bash
)。 举一个例子,我们如何来回传递消息:
灰:
#!/bin/sh MESSAGE="hello" . ./b.sh echo "[A] The message is: $MESSAGE"
b.sh:
#!/bin/sh echo "[B] The message is: $MESSAGE" MESSAGE="goodbye"
然后:
$ ./a.sh [B] The message is: hello [A] The message is: goodbye
这在bash
同样适用。 它还可以轻松地共享更复杂的数据,这些数据不能expression为环境variables(至less在您不太重视的情况下),比如数组或关联数组。
致命错误给了一个直截了当的可能性:来源你的第二个脚本! 如果你担心这第二个脚本可能会改变你的一些宝贵的variables,你总是可以在一个子shell中find它:
( . ./test2.sh )
括号会使源代码在子shell中发生,这样父shell将不会看到test2.sh
可以执行的修改。
还有另外一种可能性,应该在这里引用: set -a
。
从POSIX set
参考 :
-a
:启用此选项时,应为每个要执行分配的variables设置导出属性; 见IEEE Std 1003.1-2001, 第4.21节“variables赋值”的基本定义卷。 如果赋值在命令中的实用名称之前,那么在实用程序完成后, 导出属性不应该保留在当前执行环境中,除了前面的一个特殊的内置实用程序导致导出属性在内置命令之后保留,已经完成。 如果赋值不在命令中的实用程序名称之前,或者赋值是getopts或read实用程序的操作的结果,则export属性应保留,直到variables未设置。
从Bash手册 :
-a
:标记为了导出到后续命令的环境而修改或创build的variables和函数。
所以在你的情况下:
set -a TESTVARIABLE=hellohelloheloo # ... # Here put all the variables that will be marked for export # and that will be available from within test2 (and all other commands). # If test2 modifies the variables, the modifications will never be # seen in the present script! set +a ./test2.sh # Here, even if test2 modifies TESTVARIABLE, you'll still have # TESTVARIABLE=hellohelloheloo
请注意,规范仅指定了set -a
variables被标记为导出。 那是:
set -a a=b set +a a=c bash -c 'echo "$a"'
会回显c
而不是空行,也不b
(即set +a
不会取消导出标记,也不会仅为导出的环境“保存”赋值的值)。 这当然是最自然的行为。
结论:使用set -a
/ set +a
可以比手动导出所有variables更加繁琐。 它优于采购第二个脚本,因为它可以用于任何命令,而不仅仅是用相同的shell语言编写的脚本。
实际上有比输出和取消设置或再次采购更简单的方法(至less在bash中,只要您手动传递环境variables即可):
让a.sh成为
#!/bin/bash secret="winkle my tinkle" echo Yo, lemme tell you \"$secret\", b.sh! Message=$secret ./b.sh
和b.sh是
#!/bin/bash echo I heard \"$Message\", yo
观察到的结果是
[rob @ Archietesting] $ ./a.sh
哟,让我告诉你“叮叮当当”b.sh!
我听说过“叮叮当当”,哟
神奇之处在于./b.sh
的最后一行,其中只有在调用./b.sh
期间, Message
才会被设置为来自./b.sh
的secret
的值。 基本上,它有点像命名参数/参数。 不止于此,它甚至适用于像$DISPLAY
这样的variables,它控制应用程序启动的X服务器。
请记住,环境variables列表的长度不是无限的。 在我的系统上,使用相对的vanilla内核, xargs --show-limits
告诉我参数缓冲区的最大大小是2094486字节。 从理论上讲,如果你的数据比这个大(pipe道,任何人?
添加到致命错误的答案,还有一种方法可以将variables传递给另一个shell脚本。
以上build议的解决scheme有一些缺点:
-
using Export
:会导致variables出现在它们的范围之外,这不是一个好的devise实践。 -
using Source
:可能会导致名称冲突或意外覆盖另一个已经获得另一个文件的其他shell脚本文件中的预定义variables。
还有另一个简单的解决scheme可供我们使用。 考虑到你发布的例子,
test.sh
#!/bin/bash TESTVARIABLE=hellohelloheloo ./test2.sh "$TESTVARIABLE"
test2.sh
#!/bin/bash echo $1
产量
hellohelloheloo
如果我们传递多个string,那么注意""
是必须的。 再举一个例子
master.sh
#!/bin/bash echo in master.sh var1="hello world" sh slave1.sh $var1 sh slave2.sh "$var1" echo back to master
slave1.sh
#!/bin/bash echo in slave1.sh echo value :$1
slave2.sh
#!/bin/bash echo in slave2.sh echo value : $1
产量
in master.sh in slave1.sh value :"hello in slave2.sh value :"hello world"
这是因为这个环节恰当地描述的原因
在Bash中,如果您使用如下所示的圆括号在子shell中导出variables,则可以避免泄露导出的variables:
#!/bin/bash TESTVARIABLE=hellohelloheloo ( export TESTVARIABLE source ./test2.sh )
这样做的好处是在从命令行运行脚本之后,您将看不到泄漏到您的环境中的$ TESTVARIABLE:
$ ./test.sh hellohelloheloo $ echo $TESTVARIABLE #empty! no leak $
另一种方式对我来说更简单一些,就是使用命名pipe道。 命名pipe道提供了一种在不同进程之间同步和发送消息的方法。
惑:
#!/bin/bash msg="The Message" echo $msg > A.pipe
B.bash:
#!/bin/bash msg=`cat ./A.pipe` echo "message from A : $msg"
用法:
$ mkfifo A.pipe #You have to create it once $ ./A.bash & ./B.bash # you have to run your scripts at the same time
B.bash将等待消息,一旦A.bash发送消息,B.bash将继续工作。
另一个select是使用eval
。 这只适用于string可信的情况。 第一个脚本可以回显variables赋值:
echo "VAR=myvalue"
然后:
eval $(./first.sh) ./second.sh
当你想设置环境variables的第二个脚本不在 bash中,而且你也不想export
variables时,这种方法是特别有趣的,可能是因为它们是敏感的,你不希望它们持续存在。