Answers:
假设您正在运行bash,请将以下代码放在要获取但不执行的脚本的开头附近:
if [ "${BASH_SOURCE[0]}" -ef "$0" ]
then
echo "Hey, you should source this script, not execute it!"
exit 1
fi
在bash下,${BASH_SOURCE[0]}
将包含shell正在读取的当前文件的名称,而不管它是源文件还是执行文件。
相反,$0
是正在执行的当前文件的名称。
-ef
测试这两个文件是否为同一文件。如果是这样,我们会提醒用户并退出。
无论是-ef
也不BASH_SOURCE
是POSIX。虽然-ef
由ksh,yash,zsh和Dash支持,但BASH_SOURCE
需要bash。 在zsh
,然而,${BASH_SOURCE[0]}
可能被替换${(%):-%N}
。
echo "Usage: source \"$myfile\""
source
不可移植。考虑到此答案是特定于bash的,虽然还不错,但是使用便携式设备是个好习惯.
不可执行的文件可以被获取但不能执行,因此,作为第一道防线,不设置可执行标志应该是一个很好的提示...
编辑:我偶然发现的把戏:使shebang成为不是shell解释器的任何可执行文件,/bin/false
使脚本返回错误(rc!= 0)
#!/bin/false "This script should be sourced in a shell, not executed directly"
bash somefile.sh
...
bash
(vd perl,python,awk ...)执行它,那么您已经看过源代码并看到说不做的评论:)
somefile.pl
Python 命名somefile.py
,所以,不,我可能还没有读过注释(这些是什么,无论如何?),而且bash somefile.sh
比chmod +x somefile.sh; ./somefile.sh
... 短
bash
)会首先尝试访问execve
文件,但是如果失败,它们会手动检查文件并手动解释#!
并通过该解释器调用它:这是#!
纯用户空间时代以来的遗留问题。约定,而不是由内核本身处理。我认为 bash
至少不会对不可执行的文件执行此操作,但是我不知道是否可以从用户可能从中调用脚本的所有shell中获得这种合理的行为。
bash
,这bash script.sh
可能是危险的。
此Stack Overflow帖子中建议了几种方法,其中,我最喜欢Wirawan Purwanto和Mr.spuratic建议的基于函数的方法:
正如Wirawan Purwanto所建议的,最可靠的方法是
FUNCNAME[1]
在一个函数中进行检查 :function mycheck() { declare -p FUNCNAME; } mycheck
然后:
$ bash sourcetest.sh declare -a FUNCNAME='([0]="mycheck" [1]="main")' $ . sourcetest.sh declare -a FUNCNAME='([0]="mycheck" [1]="source")'
这等效于检查
caller
,值 的输出main
并source
区分调用者的上下文。使用FUNCNAME[]
保存您捕获和解析caller
输出。不过,您需要知道或计算本地通话深度是否正确。诸如从其他函数或脚本中获取脚本的情况将导致数组(堆栈)更深。(FUNCNAME
是一个特殊的bash数组变量,它应该具有与调用堆栈相对应的连续索引,只要它从不为准unset
。)
因此,您可以添加到脚本的开头:
function check()
{
if [[ ${FUNCNAME[-1]} != "source" ]] # bash 4.2+, use ${FUNCNAME[@]: -1} for older
then
printf "Usage: source %s\n" "$0"
exit 1
fi
}
check
当您获取shell脚本时,shebang行将被忽略。通过输入无效的shebang,您可以提醒用户该脚本已错误执行:
#!/bin/bash source-this-script
# ...
错误消息将是这样的:
/bin/bash: source-this-script: No such file or directory
(任意)参数名称已经提供了很强的提示,但是错误消息仍然不是100%清晰。我们可以使用实用程序脚本来解决此问题,该脚本source-this-script
位于您的某个位置PATH
:
#!/bin/sh
echo >&2 "This script must be sourced, not executed${1:+: }${1:-!}"
exit 1
现在,错误消息将是这样的:
This script must be sourced, not executed: path/to/script.sh
与其他答案相比,此方法只需要对每个脚本进行最少的更改(并且具有shebang行有助于编辑器中的文件类型检测并指定shell脚本方言,因此甚至有好处)。不利之处是有些不清楚的错误消息,或者(一次性)添加了另一个shell脚本。
但是,它不会阻止通过显式调用bash path/to/script.sh
(感谢@muru!)。
bash some/script.sh
,也将忽略shebang。
#!/bin/echo 'You must source this script!'
或类似的方式使消息更清晰。
x
仅包含命令的单行shell脚本,就. your-script-to-be-sourced
可以了,但是如果他想执行bash your-script-to-be-sourced
该脚本,应该禁止它吗?此限制的意义是什么?