Bash 在两个独立的shell脚本之间共享变量

Bash 在两个独立的shell脚本之间共享变量,bash,shell,Bash,Shell,我正试图从一个脚本中导出一个变量,并在另一个脚本中使用它,但该变量未被导出。可能是什么问题 将此视为脚本1 #!/bin/sh export x=19 exit 0 将此视为脚本2 #!/bin/sh echo "x="${x} exit 0 我将它们作为两个独立的脚本执行,如 desktop:~/Desktop/Trail_Programs$ sh script1.sh desktop:~/Desktop/Trail_Programs$ sh script2.sh 输出是 desktop

我正试图从一个脚本中导出一个变量,并在另一个脚本中使用它,但该变量未被导出。可能是什么问题

将此视为脚本1

#!/bin/sh
export x=19
exit 0
将此视为脚本2

#!/bin/sh
echo "x="${x}
exit 0
我将它们作为两个独立的脚本执行,如

desktop:~/Desktop/Trail_Programs$ sh script1.sh
desktop:~/Desktop/Trail_Programs$ sh script2.sh
输出是

desktop:~/Desktop/Trail_Programs$ sh script2.sh 
x=

source
script1.sh
来自
script2.sh

script2.sh的开头(在shebang之后),添加:


假设您有一个包含以下内容的文件

#this file tobeincluded1 will be included in master
x=16
#this file tobeincluded2 will be included in master
y=21
以及包含以下内容的文件
2

#this file tobeincluded1 will be included in master
x=16
#this file tobeincluded2 will be included in master
y=21
您可以使用
源代码将上述文件包括在脚本中,如下所示:

#!/bin/bash

. ./tobeincluded1   #using the . to include a file
source ./tobeincluded2 #using the source command to include a file

echo "x : $x"
echo "y : $y"

请记住,脚本可能永远不会影响其父环境从不表示从不。因此,遵循规则:

#!/bin/bash
export x=19
exit 0
对环境没有影响,并且不会在那里设置
x=anything
。导出只会影响从该脚本中创建的子shell的环境。例如,将脚本称为
exp.sh

#!/bin/bash
export x=19
./script2.sh
exit 0
#!/bin/sh
export x=19
# Write to temp. file named for the *parent* process ID.
# Since both script calls will have the same parent process, this 
# allows you to avoid a static filename subject to name collisions.
printf %s "$x" > /tmp/x.$PPID
#!/bin/sh
# Read the value of $x from the temp. file, then delete the file.
x=$(cat /tmp/x.$PPID) && rm /tmp/x.$PPID
echo "x=${x}"
script2.sh
中,您有:

echo "x = $x"
只有到那时,你才能得到:

$ bash exp.sh
x = 19
这就是规则…

解释了代码不起作用的原因

注:
只有在不允许修改您使用的脚本的情况下,才应使用以下解决方案(如果您想了解源代码和特殊环境变量,该解决方案可能也很有用)。
否则,请参阅底部讨论的解决方案。

要解决您的问题,您可以尝试以下方法:

x=$(trap 'printf %s "$x"' EXIT; . script1.sh >/dev/null) sh script2.sh
然而,请注意:

  • script1.sh
    将(必要时)由您当前的shell执行,它可能是也可能不是
    sh
  • script1.sh
    的标准输出被抑制,因为必须确保
    printf%s“$x”
    是命令替换中的子shell生成的唯一标准输出(
    $(…)
  • 这种方法仅限于一个变量(尽管可以将其扩展为输出多个变量的值,然后调用脚本必须将这些值解析回单个值)
。script1.sh
在子shell中生成脚本,这意味着子shell直接在自己的环境中执行
script1.sh
,因此在执行脚本后可以看到脚本的变量(这意味着即使未导出脚本,也会看到
$x

trap'printf%s“$x”退出
设置退出陷阱;i、 例如,当子shell退出时执行的代码,在本例中为
printf%s“$x”
,它只输出感兴趣的变量的值。
请注意,这种方法对于确保打印
$x
的值是必要的,即使
script1.sh
由于
exit
语句而终止;由于
script1.sh
是由子shell提供的源代码,
exit
退出整个子shell

x=$(…)
捕获该值,并通过在命令
sh script2.sh
前面加上前缀,有效地使生成的
$x
成为
script2.sh
可以看到的环境变量


一般来说,源代码脚本不是为源代码设计的,这是有问题的:

  • 脚本修改或创建的所有变量以及脚本对shell环境执行的任何更改都将影响调用shell
  • 如果这些脚本执行
    exit
    ,它们也将退出调用shell
如果由于某种原因无法修改所涉及的脚本,则上述解决方案是最佳选择,因为它绕过了这些问题,尽管存在一些限制


更健壮的通用解决方案(需要修改脚本):

让设置感兴趣的环境变量的脚本本身调用另一个脚本是正确的解决方案,如中所示

如果脚本确实需要作为对等方运行,则需要通过文件传递值:让设置感兴趣的变量的脚本将其值写入(临时)文件,并让其他脚本读取该文件:

script1.sh

#!/bin/bash
export x=19
./script2.sh
exit 0
#!/bin/sh
export x=19
# Write to temp. file named for the *parent* process ID.
# Since both script calls will have the same parent process, this 
# allows you to avoid a static filename subject to name collisions.
printf %s "$x" > /tmp/x.$PPID
#!/bin/sh
# Read the value of $x from the temp. file, then delete the file.
x=$(cat /tmp/x.$PPID) && rm /tmp/x.$PPID
echo "x=${x}"
script2.sh

#!/bin/bash
export x=19
./script2.sh
exit 0
#!/bin/sh
export x=19
# Write to temp. file named for the *parent* process ID.
# Since both script calls will have the same parent process, this 
# allows you to avoid a static filename subject to name collisions.
printf %s "$x" > /tmp/x.$PPID
#!/bin/sh
# Read the value of $x from the temp. file, then delete the file.
x=$(cat /tmp/x.$PPID) && rm /tmp/x.$PPID
echo "x=${x}"

++; 但是
/script2.sh
并没有创建子shell,它创建了一个恰好是shell的子进程。导出的变量成为对任何子进程可见的环境变量,无论它是否为shell;另外,我建议说“不能影响其父环境”。假设我必须独立执行这两个脚本,这两个脚本之间没有父子关系,那么我该怎么办?您违反了规则。当您需要在您的环境中设置某些内容时。您仅限于
/etc/profile
/etc/bashrc
$HOME
中的版本(例如
~/.bashrc
)。这就是Linux shell的工作方式。您可以
source
将包含变量的代码写入当前shell/脚本,但不能影响父级。考虑一下
PS1
PATH
的设置位置和方式。这就是原因。您总是可以编写一个
tmp
文件,并从
script2
读取该文件,您就是不能使用环境。@mklement0一如既往,您的措辞是正确的,我本来可以用更好的措词....@DavidC.Rankin写入tmp文件会创建一个tmp~文件,script1会从tmp~文件中读取数据,这是堆栈溢出中的常见问题,这两个问题都是非常常见的问题。虽然这在某些情况下可能有效,通常情况下,源代码脚本不是为源代码设计的,这是有问题的。除了可能污染调用shell的环境外,更大的问题是源代码脚本中的
exit
语句(如图所示)