【问题标题】:Exporting variables between shell script在 shell 脚本之间导出变量
【发布时间】:2011-04-15 13:22:40
【问题描述】:

我有两个独立运行的脚本。 第一个假设脚本 A 计算一些值。我想从其他名为 B 的脚本中回显这些值。这些脚本不会相互调用。我使用了 export 关键字,但没有用。我该怎么做?

【问题讨论】:

标签: bash shell scripting


【解决方案1】:

如果我理解要求,那么两个脚本不能简单地在同一个子 shell 中执行,独立但没有相互调用或不需要像这样的外部文件或管道:

假设这是你的 script1.sh

#!/bin/bash
# script1.sh: do something and finally
export x=19

这里是您的 script2.sh

#!/bin/bash
# script2.sh: read value of $x here
echo "x="${x}

像这样在同一个子shell中调用它们

(. ./script1.sh && ./script2.sh)

输出:

x=19

【讨论】:

    【解决方案2】:
     mkfifo /tmp/channel
    
     process_a.sh > /tmp/channel&
     process_b.sh < /tmp/channel&
    
     wait
    

    当然,您也可以在需要时只读取一行。

    在 bash 中有 coprocs,这也可能是您想要的。来自this page的随机示例

    # let the output of the coprocess go to stdout
    { coproc mycoproc { awk '{print "foo" $0;fflush()}' ;} >&3 ;} 3>&1
    echo bar >&${mycoproc[1]}
    foobar
    

    显然,ksh 也有类似的功能

    【讨论】:

    • 独立进程之间的通信最容易通过文件来完成,命名管道提供了一个方便的类似文件的接口:A "FIFO" is a special file type that permits independent processes to communicate.
    • coproc 很有趣。我去看看。
    【解决方案3】:

    将每个脚本视为一个函数:函数 A 计算某个值并返回它。它不知道谁会打电话给它。函数 B 接受一些值并回显它。它不关心是谁产生了这个价值。所以,脚本 A 是:

    #!/bin/sh
    # a.sh: Calculate something and return the result
    echo 19
    

    脚本 B 是:

    #!/bin/sh
    # b.sh: Consume the calculated result, which passed in as $1
    echo The result is $1
    

    使它们可执行:

    chmod +x [ab].sh
    

    现在,我们可以在命令行中将它们粘合在一起:

    $ b.sh $(a.sh)
    The result is 19
    

    在语义上,b.sh 没有调用 a.sh。您调用了 a.sh 并将其结果传递给 b.sh。

    【讨论】:

      【解决方案4】:

      你不能读取第三个文件吗,比如说 settings.sh 和常见的导出变量?

      # common.sh
      export MY_PATH=/home/foo/bar/
      export VERSION=42.2a
      

      并在 A 和 B source common.sh 中加载这些值。

      请注意,在这种情况下可能不需要导出。

      【讨论】:

      • 我实际上不需要第三个文件。
      【解决方案5】:

      您可以将值回显到文件中,然后其他脚本可以读取它们。如果您想将其用作某事的参数,请使用反撇号:

      echo `cat storedvalue`
      

      请注意,如果两个脚本同时运行,可能会出现并发问题,这可能会导致很少出现、看起来很神秘的错误。

      【讨论】:

      • 那么如何将脚本 A 的返回值传递给脚本 B?
      【解决方案6】:

      其实你只需要source,你可以跳过export前缀。

      我的用例是一个特定于环境的设置文件,例如:

      ma​​in_script.sh

      THIS_DIR=`dirname $0`
      source $THIS_DIR/config_vars.sh
      # other commands
      

      config_vars.sh

      LOCAL_ROOT="$HOME/folder/folder"
      REMOTE_USERNAME='someuser'
      BACKUP_FOLDER="$LOCAL_ROOT/folder"
      # etc.
      

      【讨论】: