bash 将所有变量从一个 shell 脚本传递到另一个?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9772036/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Pass all variables from one shell script to another?
提问by Toskan
Lets say I have a shell / bash script named test.sh
with:
假设我有一个 shell/bash 脚本,命名test.sh
为:
#!/bin/bash
TESTVARIABLE=hellohelloheloo
./test2.sh
My test2.sh
looks like this:
我的test2.sh
看起来像这样:
#!/bin/bash
echo ${TESTVARIABLE}
This does not work. I do not want to pass all variables as parameters since imho this is overkill.
这不起作用。我不想将所有变量作为参数传递,因为恕我直言,这太过分了。
Is there a different way?
有不同的方法吗?
回答by FatalError
You have basically two options:
您基本上有两种选择:
- Make the variable an environment variable (
export TESTVARIABLE
) before executing the 2nd script. - Source the 2nd script, i.e.
. test2.sh
and it will run in the same shell. This would let you share more complex variables like arrays easily, but also means that the other script could modify variables in the source shell.
export TESTVARIABLE
在执行第二个脚本之前将该变量设置为环境变量 ( )。- 源第二个脚本,即
. test2.sh
它会在同一个 shell 中运行。这将使您可以轻松共享更复杂的变量,如数组,但也意味着其他脚本可以修改源 shell 中的变量。
UPDATE:
更新:
To use export
to set an environment variable, you can either use an existing variable:
要用于export
设置环境变量,您可以使用现有变量:
A=10
# ...
export A
This ought to work in both bash
and sh
. bash
also allows it to be combined like so:
这应该适用于bash
和sh
。 bash
也允许它像这样组合:
export A=10
This also works in mysh
(which happens to be bash
, you can use echo $SHELL
to check). But I don't believe that that's guaranteed to work in all sh
, so best to play it safe and separate them.
这也适用于我的sh
(恰好是bash
,您可以echo $SHELL
用来检查)。但我不相信这能保证在所有情况下都有效sh
,所以最好谨慎行事并将它们分开。
Any variable you export in this way will be visible in scripts you execute, for example:
您以这种方式导出的任何变量都将在您执行的脚本中可见,例如:
a.sh:
灰:
#!/bin/sh
MESSAGE="hello"
export MESSAGE
./b.sh
b.sh:
b.sh:
#!/bin/sh
echo "The message is: $MESSAGE"
Then:
然后:
$ ./a.sh
The message is: hello
The fact that these are both shell scripts is also just incidental. Environment variables can be passed to any process you execute, for example if we used python instead it might look like:
这些都是 shell 脚本的事实也只是偶然的。环境变量可以传递给您执行的任何进程,例如,如果我们使用 python,它可能看起来像:
a.sh:
灰:
#!/bin/sh
MESSAGE="hello"
export MESSAGE
./b.py
b.py:
b.py:
#!/usr/bin/python
import os
print 'The message is:', os.environ['MESSAGE']
Sourcing:
采购:
Instead we could source like this:
相反,我们可以这样获取:
a.sh:
灰:
#!/bin/sh
MESSAGE="hello"
. ./b.sh
b.sh:
b.sh:
#!/bin/sh
echo "The message is: $MESSAGE"
Then:
然后:
$ ./a.sh
The message is: hello
This more or less "imports" the contents of b.sh
directly and executes it in the same shell. Notice that we didn't have to export the variable to access it. This implicitly shares all the variables you have, as well as allows the other script to add/delete/modify variables in the shell. Of course, in this model both your scripts should be the same language (sh
or bash
). To give an example how we could pass messages back and forth:
这或多或少会b.sh
直接“导入” 的内容并在同一个 shell 中执行它。请注意,我们不必导出变量即可访问它。这隐式共享您拥有的所有变量,并允许其他脚本在 shell 中添加/删除/修改变量。当然,在此模型中,您的两个脚本都应使用相同的语言(sh
或bash
)。举个例子,我们如何来回传递消息:
a.sh:
灰:
#!/bin/sh
MESSAGE="hello"
. ./b.sh
echo "[A] The message is: $MESSAGE"
b.sh:
b.sh:
#!/bin/sh
echo "[B] The message is: $MESSAGE"
MESSAGE="goodbye"
Then:
然后:
$ ./a.sh
[B] The message is: hello
[A] The message is: goodbye
This works equally well in bash
. It also makes it easy to share more complex data which you could not express as an environment variable (at least without some heavy lifting on your part), like arrays or associative arrays.
这在bash
. 它还可以轻松共享更复杂的数据,这些数据您无法表示为环境变量(至少在您没有做一些繁重的工作时),例如数组或关联数组。
回答by gniourf_gniourf
Fatal Error gave a straightforward possibility: source your second script! if you're worried that this second script may alter some of your precious variables, you can always source it in a subshell:
致命错误给出了一个简单的可能性:源你的第二个脚本!如果您担心第二个脚本可能会改变您的一些宝贵变量,您可以随时在子 shell 中获取它:
( . ./test2.sh )
The parentheses will make the source happen in a subshell, so that the parent shell will not see the modifications test2.sh
could perform.
括号将使源发生在子外壳中,因此父外壳不会看到test2.sh
可以执行的修改。
There's another possibility that should definitely be referenced here: use set -a
.
这里绝对应该引用另一种可能性:使用set -a
.
From the POSIX set
reference:
-a
: When this option is on, the exportattribute shall be set for each variable to which an assignment is performed; see the Base Definitions volume of IEEE Std 1003.1-2001, Section 4.21, Variable Assignment. If the assignment precedes a utility name in a command, the exportattribute shall not persist in the current execution environment after the utility completes, with the exception that preceding one of the special built-in utilities causes the exportattribute to persist after the built-in has completed. If the assignment does not precede a utility name in the command, or if the assignment is a result of the operation of the getoptsor readutilities, the export attribute shall persist until the variable is unset.
-a
: 当这个选项打开时,应该为每个执行赋值的变量设置导出属性;请参阅 IEEE Std 1003.1-2001 的基本定义卷,第 4.21 节,变量分配。如果赋值位于命令中的实用程序名称之前,则在实用程序完成后,导出属性将不会在当前执行环境中持续存在,但特殊内置实用程序之一的前面会导致导出属性在内置实用程序之后持续存在。在已经完成。如果赋值不在命令中的实用程序名称之前,或者如果赋值是getopts或read操作的结果实用程序,导出属性应持续到变量未设置为止。
From the Bash Manual:
来自Bash 手册:
-a
: Mark variables and function which are modified or created for export to the environment of subsequent commands.
-a
: 标记修改或创建的变量和函数,以便导出到后续命令的环境中。
So in your case:
所以在你的情况下:
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
Observe that the specs only specify that with set -a
the variable is markedfor export. That is:
请注意,规范仅指定set -a
将变量标记为导出。那是:
set -a
a=b
set +a
a=c
bash -c 'echo "$a"'
will echo c
and not an empty line nor b
(that is, set +a
doesn't unmark for export, nor does it “save” the value of the assignment only for the exported environment). This is, of course, the most natural behavior.
将回显c
而不是空行或b
(即,set +a
不会取消标记导出,也不会“保存”仅用于导出环境的分配值)。当然,这是最自然的行为。
Conclusion: using set -a
/set +a
can be less tedious than exporting manually all the variables. It is superior to sourcing the second script, as it will work for any command, not only the ones written in the same shell language.
结论:使用set -a
/set +a
可以比手动导出所有变量更乏味。它优于采购第二个脚本,因为它适用于任何命令,而不仅仅是用相同的 shell 语言编写的命令。
回答by striking
There's actually an easier way than exporting and unsetting or sourcing again (at least in bash, as long as you're ok with passing the environment variables manually):
实际上有一种比导出和取消设置或再次获取更简单的方法(至少在 bash 中,只要您可以手动传递环境变量):
let a.sh be
让 a.sh 成为
#!/bin/bash
secret="winkle my tinkle"
echo Yo, lemme tell you \"$secret\", b.sh!
Message=$secret ./b.sh
and b.sh be
和 b.sh 是
#!/bin/bash
echo I heard \"$Message\", yo
Observed output is
观察到的输出是
[rob@Archie test]$ ./a.sh
Yo, lemme tell you "winkle my tinkle", b.sh!
I heard "winkle my tinkle", yo
[rob@Archie 测试]$ ./a.sh
哟,让我告诉你“眨眨眼”,b.sh!
我听到了“眨眼我的叮当声”,哟
The magic lies in the last line of a.sh
, where Message
, for only the duration of the invocation of ./b.sh
, is set to the value of secret
from a.sh
.
Basically, it's a little like named parameters/arguments. More than that, though, it even works for variables like $DISPLAY
, which controls which X Server an application starts in.
神奇之处在于 的最后一行a.sh
,其中Message
仅在调用 的持续时间内./b.sh
, 被设置为secret
from的值a.sh
。基本上,它有点像命名参数/参数。更重要的是,它甚至适用于诸如$DISPLAY
控制应用程序在哪个 X 服务器中启动的变量。
Remember, the length of the list of environment variables is not infinite. On my system with a relatively vanilla kernel, xargs --show-limits
tells me the maximum size of the arguments buffer is 2094486 bytes. Theoretically, you're using shell scripts wrong if your data is any larger than that (pipes, anyone?)
请记住,环境变量列表的长度不是无限的。在我的具有相对普通内核的系统上,xargs --show-limits
告诉我参数缓冲区的最大大小是 2094486 字节。从理论上讲,如果您的数据大于该值(管道,有人吗?)
回答by Subham Tripathi
Adding to the answer of Fatal Error, There is one more way to pass the variables to another shell script.
除了致命错误的答案之外,还有一种方法可以将变量传递给另一个 shell 脚本。
The above suggested solution have some drawbacks:
上述建议的解决方案有一些缺点:
using Export
: It will cause the variable to be present out of their scope which is not a good design practice.using Source
: It may cause name collisions or accidental overwriting of a predefined variable in some other shell script file which have sourced another file.
using Export
:这会导致变量超出其范围,这不是一个好的设计实践。using Source
: 它可能会导致名称冲突或意外覆盖某些其他 shell 脚本文件中的预定义变量,这些文件来源于另一个文件。
There is another simple solution avaiable for us to use. Considering the example posted by you,
还有另一个简单的解决方案可供我们使用。考虑到您发布的示例,
test.sh
测试文件
#!/bin/bash
TESTVARIABLE=hellohelloheloo
./test2.sh "$TESTVARIABLE"
test2.sh
测试2.sh
#!/bin/bash
echo
output
输出
hellohelloheloo
Also it is important to note that ""
are necessary if we pass multiword strings.
Taking one more example
同样重要的是要注意,""
如果我们传递多字字符串,这是必要的。再举一个例子
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
slave1.sh
#!/bin/bash
echo in slave1.sh
echo value :
slave2.sh
slave2.sh
#!/bin/bash
echo in slave2.sh
echo value :
output
输出
in master.sh
in slave1.sh
value :"hello
in slave2.sh
value :"hello world"
It happens because of the reasons aptly described in this link
它的发生是由于此链接中恰当描述的原因
回答by Riaz Rizvi
In Bash if you export the variable within a subshell, using parentheses as shown, you avoid leaking the exported variables:
在 Bash 中,如果您在子 shell 中导出变量,使用如图所示的括号,可以避免泄漏导出的变量:
#!/bin/bash
TESTVARIABLE=hellohelloheloo
(
export TESTVARIABLE
source ./test2.sh
)
The advantage here is that after you run the script from the command line, you won't see a $TESTVARIABLE leaked into your environment:
这里的优点是,从命令行运行脚本后,您不会看到 $TESTVARIABLE 泄漏到您的环境中:
$ ./test.sh
hellohelloheloo
$ echo $TESTVARIABLE
#empty! no leak
$
回答by Mark Stosberg
Another option is using eval
. This is only suitable if the strings are trusted. The first script can echo the variable assignments:
另一种选择是使用eval
. 这仅适用于信任字符串的情况。第一个脚本可以回显变量分配:
echo "VAR=myvalue"
echo "VAR=myvalue"
Then:
然后:
eval $(./first.sh) ./second.sh
eval $(./first.sh) ./second.sh
This approach is of particular interest when the second script you want to set environment variables for is notin bash and you also don't want to export
the variables, perhaps because they are sensitive and you don't want them to persist.
当您要为其设置环境变量的第二个脚本不在bash 中并且您也不想要export
这些变量时,这种方法特别有趣,这可能是因为它们很敏感并且您不希望它们持续存在。
回答by Pejman Habashi
Another way, which is a little bit easier for me is to use named pipes. Named pipes provided a way to synchronize and sending messages between different processes.
另一种对我来说更容易的方法是使用命名管道。命名管道提供了一种在不同进程之间同步和发送消息的方法。
A.bash:
惑:
#!/bin/bash
msg="The Message"
echo $msg > A.pipe
B.bash:
B.bash:
#!/bin/bash
msg=`cat ./A.pipe`
echo "message from A : $msg"
Usage:
用法:
$ 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 will wait for message and as soon as A.bash sends the message, B.bash will continue its work.
B.bash 将等待消息,一旦 A.bash 发送消息,B.bash 将继续其工作。