可以说我有一个名为/的shell / bash脚本test.sh
:
#!/bin/bash
TESTVARIABLE=hellohelloheloo
./test2.sh
我的test2.sh
样子是这样的:
#!/bin/bash
echo ${TESTVARIABLE}
这是行不通的。我不想将所有变量都作为参数传递,因为恕我直言,这太过分了。
有其他方法吗?
可以说我有一个名为/的shell / bash脚本test.sh
:
#!/bin/bash
TESTVARIABLE=hellohelloheloo
./test2.sh
我的test2.sh
样子是这样的:
#!/bin/bash
echo ${TESTVARIABLE}
这是行不通的。我不想将所有变量都作为参数传递,因为恕我直言,这太过分了。
有其他方法吗?
Answers:
您基本上有两种选择:
export TESTVARIABLE
在执行第二个脚本之前,将变量设置为环境变量()。. test2.sh
它将在同一外壳中运行。这将使您轻松共享数组等更复杂的变量,但也意味着其他脚本可以在源shell中修改变量。更新:
要用于export
设置环境变量,可以使用现有变量:
A=10
# ...
export A
这应该同时适用于bash
和sh
。 bash
还允许将其合并,如下所示:
export A=10
这也适用于我 sh
(碰巧是bash
,您可以echo $SHELL
用来检查)。但是我不认为这可以保证全部工作sh
,因此最好谨慎使用并将它们分开。
您以这种方式导出的任何变量将在您执行的脚本中可见,例如:
灰:
#!/bin/sh
MESSAGE="hello"
export MESSAGE
./b.sh
b.sh:
#!/bin/sh
echo "The message is: $MESSAGE"
然后:
$ ./a.sh
The message is: hello
这些都是shell脚本的事实也是偶然的。可以将环境变量传递给您执行的任何进程,例如,如果我们改用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
直接“导入”了内容并在同一shell中执行。注意,我们不必导出变量即可访问它。这隐式共享您拥有的所有变量,并允许其他脚本在外壳中添加/删除/修改变量。当然,在此模型中,两个脚本都应使用相同的语言(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
。它也使共享数组或关联数组之类的更复杂的数据变得容易,而这些数据无法表达为环境变量(至少没有付出很大的努力)。
致命错误提供了一种直接的可能性:编写第二个脚本!如果您担心第二个脚本可能会更改一些宝贵的变量,则可以始终在子shell中提供它:
( . ./test2.sh )
括号将使源代码出现在子shell中,因此父shell将看不到修改test2.sh
可以执行的情况。
这里肯定还有另外一种可能需要引用:use set -a
。
-a
:启用此选项时,应为每个要执行赋值的变量设置导出属性;请参阅《 IEEE标准1003.1-2001的基本定义》第4.21节“变量赋值”。如果分配在命令中位于实用程序名称之前,则该实用程序完成后,export属性不应在当前执行环境中保留,但特殊的内置实用程序之一的前面会导致export属性在内置的实用程序之后持续存在。中已完成。如果该赋值不在命令中的实用程序名称之前,或者该赋值是getopts或read操作的结果 实用程序中,导出属性将一直存在,直到未设置变量为止。
从Bash手册:
-a
:标记为导出到后续命令环境而修改或创建的变量和函数。
因此,在您的情况下:
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
的变量。那是:
set -a
a=b
set +a
a=c
bash -c 'echo "$a"'
将回显c
而不是空行b
(即,set +a
不取消标记为导出,也不会仅为导出的环境“保存”分配的值)。当然,这是最自然的行为。
结论:使用set -a
/ set +a
可以比手动导出所有变量少乏味。它比采购第二个脚本优越,因为它适用于任何命令,不仅适用于使用相同Shell语言编写的命令。
实际上,有比重新导出和取消设置或重新寻找资源更简单的方法(至少在bash中,只要您可以手动传递环境变量即可):
让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 @ Archie test] $ ./a.sh
哟,lemme告诉你“眨眼我的叮当声”,b.sh!
我听到“我的叮当声”,哟
神奇之处在于的最后一行a.sh
,其中Message
仅在调用的持续时间内./b.sh
,将其设置为secret
from 的值a.sh
。基本上,它有点像命名参数/参数。不仅如此,它甚至还适用于变量,例如$DISPLAY
,它控制应用程序从哪个X Server启动。
请记住,环境变量列表的长度不是无限的。在具有相对xargs --show-limits
原始内核的系统上,告诉我参数缓冲区的最大大小为2094486字节。从理论上讲,如果您的数据大于该范围(管道,任何人?),则您使用的Shell脚本是错误的
除了致命错误的答案之外,还有另一种将变量传递给另一个Shell脚本的方法。
上述建议的解决方案有一些缺点:
using Export
:这将导致变量超出其范围,这不是一个好的设计实践。using Source
:这可能会导致名称冲突或意外地覆盖源于另一个文件的某些其他Shell脚本文件中的预定义变量。有另一个简单的解决方案可供我们使用。考虑到您发布的示例,
test.sh
#!/bin/bash
TESTVARIABLE=hellohelloheloo
./test2.sh "$TESTVARIABLE"
test2.sh
#!/bin/bash
echo $1
输出
hellohelloheloo
同样重要的是要注意,""
如果我们传递多字字符串,这是必需的。再举一个例子
大师
#!/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"
发生这种情况是由于此链接中恰当描述的原因
source
实际上是一件好事。关于您的担心:意外覆盖预定义变量,您始终可以在subshell中进行获取。那完全解决了问题。
( . ./test2.sh )
。括号将使Bash在子shell中运行其内容。
在Bash中,如果您使用如图所示的括号将变量导出到子外壳中,则可以避免泄漏导出的变量:
#!/bin/bash
TESTVARIABLE=hellohelloheloo
(
export TESTVARIABLE
source ./test2.sh
)
这样做的好处是,从命令行运行脚本后,您不会看到$ TESTVARIABLE泄漏到您的环境中:
$ ./test.sh
hellohelloheloo
$ echo $TESTVARIABLE
#empty! no leak
$
$
提示符)将永远不会看到导出的,因此实际上不需要该子Shell $TESTVARIABLE
。导出只是将变量的副本传递给任何后续的子进程。除非将值保存到存储器中,然后再在父过程脚本中读取该存储器,否则不可能将变量传递回链到父过程。可以使用父脚本的第二个副本,但这不是同一过程。在这里可以找到很好的解释。
另一种方法(对我来说更容易一点)是使用命名管道。命名管道提供了一种在不同进程之间同步和发送消息的方法。
惑:
#!/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将继续其工作。