【问题标题】:How can I source multiple bash scripts into each others properly?如何正确地将多个 bash 脚本相互提供?
【发布时间】:2017-05-01 14:57:25
【问题描述】:

假设我有以下脚本文件:

~/src/setup.sh::

#!/usr/bin/env bash

dn=$( dirname "$0" )
source "$dn/init/init.sh"

~/src/init/init.sh:

#!/usr/bin/env bash

dn=$( dirname "$0" )
source "$dn/start.sh"

start_servers "param1" "param2"

~/src/init/start.sh:

#!/usr/bin/env bash

start_servers() {
  # ...
  printf "start the servers..."
  # ...
}

获取第二个文件 (start.sh) 会导致:

$ ./setup.sh
./init/init.sh: line 4: ./start.sh: No such file or directory
./init/init.sh: line 6: start_servers: command not found

由于我从. 执行 setup.sh,在获取文件后,start.sh 似乎也来自.,但我会喜欢从适当的位置获取它。

知道如何解决吗?提前致谢。

【问题讨论】:

  • $0 在源脚本中将是父级的$0,这就是失败的原因。参见this answer了解如何确定当前脚本文件的位置
  • source 将搜索$PATH 中的目录。也许你应该把包含所有这些脚本的目录放在$PATH中。
  • 这里还有一个潜在的问题:即使修复了这个问题,setup.sh 将dn 设置为~/src,然后init.sh 将其设置为~/src/init;当 init.sh 完成时,它仍然会被设置为 ~/src/init,所以如果 setup.sh 在获取 init.sh 之后使用它,它不会指向预期的位置。
  • @GordonDavisson:真的,谢谢!

标签: bash shell unix path


【解决方案1】:

如果你使用sh而不是source,它会按照你的预期加载环境,而不是在同一个环境中执行脚本:

dn=$( dirname "$0" )
sh "$dn/init/init.sh"

此更改将导致代码在子 shell 中运行,而不是在同一个 shell 中。对于需要来自外壳的函数的脚本,您将无法执行此操作,因为您仍然需要获取该函数才能访问该函数。但是在您的情况下,仍然可以获取唯一需要的脚本,因为那里不需要 $0。

【讨论】:

  • 如果start.sh 在子shell 中运行,start_servers 将不可用于init.sh。
  • start.sh 无论如何都不使用 $0,因此您可以将其保留为源,并且 start_servers 仍然可以工作。
  • 仅供参考,您不应该仅仅因为它们不是您最喜欢的答案而对答案投反对票。支持你最喜欢的那些,只反对严重错误的信息。即使这样,您也应该先尝试用 cmets 纠正它,并且只有在发布者拒绝纠正错误信息时才投反对票。我的可能不是给定问题的最终解决方案,但它是可用的。
  • 我没有投反对票,但@JohnKugelman 指出了您回答中的一个根本缺陷:如果您将所有source 呼叫替换为您似乎推荐的sh 呼叫 ("在每个脚本中进行此更改”),函数start_servers() 将在init.sh 中不可用。除此之外,您不应该使用sh 调用为bash 编写的脚本。最后是挑剔:将脚本传递给sh 不会在subshel​​l 中运行它,而是在恰好是shell 的子进程 中运行。跨度>
  • 谢谢,这比投反对票更有帮助。但是有一个问题,subshel​​l 的定义不是“恰好是一个 shell 的子进程”吗?还是在 linux 中有一些有意义的概念,subshel​​l 所指的与此不同?
【解决方案2】:

Bash 有内置的$BASH_SOURCE 变量,它类似于$0,但与后者不同的是,即使在来源时也能正确反映正在运行的脚本的名称。

因此,只需在脚本中将$0 替换为$BASH_SOURCE 就足够了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-01
    相关资源
    最近更新 更多