我有一个脚本,如果它被源引用,我不想让它调用exit
。
我考虑检查$0 == bash
,但是如果脚本从另一个脚本中被源引用,或者用户从不同的shell(如ksh
)中源引用它,则存在问题。
有没有一种可靠的方法来检测脚本是否正在被源引用?
我需要一个适用于 [mac, linux] 并且 bash 版本 >= 3 的一行代码,但是这些答案都不符合要求。
[[ ${BASH_SOURCE[0]} = $0 ]] && main "$@"
另一种解决方案(依赖于GNU coreutils中的readlink):
if [ "$(readlink -f "$(command -v "$0")")" != "$(readlink -f /proc/$$/exe)" ]; then
echo "Is executed"
fi
这个比较:
这是从其他答案中分离出来的,与“通用”的跨shell支持有关。尽管略有不同,但这与https://dev59.com/GXE85IYBdhLWcg3wpFEa#2942183非常相似。其弱点在于客户端脚本必须尊重如何使用它(即首先导出一个变量)。优点是这很简单,应该可以在“任何地方”工作。以下是您可以剪切和粘贴的模板:
# NOTE: This script may be used as a standalone executable, or callable library.
# To source this script, add the following *prior* to including it:
# export ENTRY_POINT="$0"
main()
{
echo "Running in direct executable context!"
}
if [ -z "${ENTRY_POINT}" ]; then main "$@"; fi
注意:我使用export
只是为了确保这种机制可以扩展到子进程中。
直截了当地说:您必须评估变量"$0"是否等于您的Shell名称。
像这样:
#!/bin/bash
echo "First Parameter: $0"
echo
if [[ "$0" == "bash" ]] ; then
echo "The script was sourced."
else
echo "The script WAS NOT sourced."
fi
通过 SHELL:
$ bash check_source.sh
First Parameter: check_source.sh
The script WAS NOT sourced.
通过 SOURCE:
$ source check_source.sh
First Parameter: bash
The script was sourced.
检测脚本是否被引用的100%可移植方式相当困难。
根据我的经验(使用Shell脚本7年),唯一安全的方法(不依赖于具有PIDs等环境变量,这是不安全的因为它是VARIABLE)是:
这两个选项都无法自动扩展,但这是更安全的方式。
#!/bin/bash
echo "First Parameter: $0"
echo
if [[ "$0" == "bash" || "$0" == "-bash" ]] ; then
echo "The script was sourced."
else
echo "The script WAS NOT sourced."
fi
或者
#!/bin/bash
echo "First Parameter: $0"
echo
if [[ "$0" == "bash" ]] ; then
echo "The script was sourced."
elif [[ "$0" == "-bash" ]] ; then
echo "The script was sourced via SSH session."
else
echo "The script WAS NOT sourced."
fi
/bin/bash -c '. ./check_source.sh'
会显示The script WAS NOT sourced.
。同样的错误:ln -s /bin/bash pumuckl; ./pumuckl -c '. ./check_source.sh'
-> The script WAS NOT sourced.
- Tino使用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 行即可。