我有一个脚本,我不希望它调用退出,如果它是来源。
我想检查是否$0 == bash,但这有问题,如果脚本是从另一个脚本,或者如果用户从不同的shell,如ksh源。
是否有一种可靠的方法来检测脚本是否被引用?
我有一个脚本,我不希望它调用退出,如果它是来源。
我想检查是否$0 == bash,但这有问题,如果脚本是从另一个脚本,或者如果用户从不同的shell,如ksh源。
是否有一种可靠的方法来检测脚本是否被引用?
当前回答
我想对丹尼斯非常有用的回答提出一个小小的更正,让它更容易携带,我希望:
[ "$_" != "$0" ] && echo "Script is being sourced" || echo "Script is a subshell"
因为[[不被Debian POSIX兼容外壳识别(有些保留的IMHO), dash。同样,在shell中,可能需要使用引号来防止文件名中包含空格。
其他回答
我认为在ksh和bash中没有任何可移植的方法来做到这一点。在bash中,您可以使用调用器输出来检测它,但我认为ksh中不存在等效的输出。
如果您的Bash版本知道BASH_SOURCE数组变量,请尝试如下操作:
# man bash | less -p BASH_SOURCE
#[[ ${BASH_VERSINFO[0]} -le 2 ]] && echo 'No BASH_SOURCE array variable' && exit 1
[[ "${BASH_SOURCE[0]}" != "${0}" ]] && echo "script ${BASH_SOURCE[0]} is being sourced ..."
这在后面的脚本中起作用,不依赖于_变量:
## Check to make sure it is not sourced:
Prog=myscript.sh
if [ $(basename $0) = $Prog ]; then
exit 1 # not sourced
fi
or
[ $(basename $0) = $Prog ] && exit
使用shebang行并检查它是否正在执行。
你的脚本应该有一行shebang #!/path/to/shell表示它应该在哪个shell中运行。否则,您还会遇到其他跨shell兼容性问题。
因此,您只需要通过尝试在源时不起作用的命令来检查它是否正在执行。
如。对于Bash脚本:
#!/usr/bin/env bash
if (return 0 2>/dev/null); then
echo "Script was sourced."
fi
这个方法也适用于zsh和sh只是改变shebang行。
解决这个问题的方法不是编写需要知道这些事情才能正确运行的代码。做到这一点的方法是将代码放入函数中,而不是放入需要源代码的脚本主线中。
函数内部的代码可以只返回0或1。这只终止了函数,因此控制返回到调用该函数的任何对象。
无论从源脚本的主线调用函数,还是从顶级脚本的主线调用函数,或者从另一个函数调用函数,都是如此。
使用sourcing来引入“库”脚本,这些脚本只定义函数和变量,但实际上不执行任何其他顶级命令:
. path/to/lib.sh # defines libfunction
libfunction arg
否则:
path/to/script.sh arg # call script as a child process
而不是:
. path/to/script.sh arg # shell programming anti-pattern