我正在定义一个用户应该source
而不是执行的 shell 脚本。
是否有一种传统的或智能的方式来提示用户这是这种情况,例如通过文件扩展名?
是否有我可以在文件本身中编写的 shell 代码,如果它被执行而不是源代码,这将导致它回显消息并退出,以便我可以帮助用户避免这个明显的错误?
Joh*_*024 54
假设您正在运行 bash,请将以下代码放在您想要获取但不执行的脚本的开头附近:
if [ "${BASH_SOURCE[0]}" -ef "$0" ]
then
echo "Hey, you should source this script, not execute it!"
exit 1
fi
Run Code Online (Sandbox Code Playgroud)
在 bash 下,${BASH_SOURCE[0]}
将包含 shell 正在读取的当前文件的名称,而不管它是源文件还是执行文件。
相比之下,$0
是正在执行的当前文件的名称。
-ef
测试这两个文件是否是同一个文件。如果是,我们会提醒用户并退出。
POSIX既不是,-ef
也不BASH_SOURCE
是。虽然-ef
由 ksh、yash、zsh 和 Dash 支持,但BASH_SOURCE
需要 bash。 在zsh
,然而,${BASH_SOURCE[0]}
可能被替换${(%):-%N}
。
xen*_*oid 36
一个不可执行的文件可以被获取但不能被执行,因此,作为第一道防线,不设置可执行标志应该是一个很好的提示......
编辑:我刚刚偶然发现的技巧:使shebang成为不是shell解释器的任何可执行文件,/bin/false
使脚本返回错误(rc!= 0)
#!/bin/false "This script should be sourced in a shell, not executed directly"
Run Code Online (Sandbox Code Playgroud)
mur*_*uru 11
这篇 Stack Overflow 帖子中建议了几种方法,其中,我最喜欢Wirawan Purwanto和mr.spuratic建议的基于函数的方法:
正如 Wirawan Purwanto 所建议的,最可靠的方法是
FUNCNAME[1]
在函数内进行检查 :Run Code Online (Sandbox Code Playgroud)function mycheck() { declare -p FUNCNAME; } mycheck
然后:
Run Code Online (Sandbox Code Playgroud)$ 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
Run Code Online (Sandbox Code Playgroud)
假设执行脚本只是无用而不是有害,您可以添加
return 0 || printf 'Must be sourced, not executed\n' >&2
Run Code Online (Sandbox Code Playgroud)
到脚本的结尾。return
除非该文件是源文件,否则函数外部具有非零退出代码。
当您获取 shell 脚本时,shebang行将被忽略。通过放入无效的shebang,您可以提醒用户脚本被错误执行:
#!/bin/bash source-this-script
# ...
Run Code Online (Sandbox Code Playgroud)
错误消息将是这样的:
/bin/bash: source-this-script: No such file or directory
Run Code Online (Sandbox Code Playgroud)
(任意)参数名称已经提供了一个强有力的提示,但错误消息仍然不是 100% 清楚。我们可以使用source-this-script
放置在您的某个位置的实用程序脚本来解决此问题PATH
:
#!/bin/sh
echo >&2 "This script must be sourced, not executed${1:+: }${1:-!}"
exit 1
Run Code Online (Sandbox Code Playgroud)
现在,错误消息将是这样的:
This script must be sourced, not executed: path/to/script.sh
Run Code Online (Sandbox Code Playgroud)
与其他答案相比,这种方法只需要对每个脚本进行最少的更改(并且使用 shebang 行有助于在编辑器中检测文件类型并指定 shell 脚本方言,因此甚至有好处)。缺点是错误消息有点不清楚,或者(一次)添加了另一个 shell 脚本。
它不会通过以下方式阻止显式调用 bash path/to/script.sh
(感谢@muru!)。
归档时间: |
|
查看次数: |
9690 次 |
最近记录: |