shell脚本是否可以测试它是否通过执行source
?也就是说,例如,
$ source myscript.sh
$ ./myscript.sh
Run Code Online (Sandbox Code Playgroud)
myscript.sh可以区分这些不同的shell环境吗?
Kur*_*fle 40
我想,Sam想要做的事可能是不可能的.
一个半假的解决方法可以在多大程度上取决于......
如果我理解Sam的要求,他想要一个'脚本'
myscript
,那就是......
myscript
(即具有chmod a-x
);sh myscript
或调用bash myscript
. myscript
首先要考虑的是这些
myscript
)调用脚本需要脚本中的第一行,如#!/bin/bash
或类似.这将直接确定将调用哪个已安装的bash可执行文件(或符号链接)实例来运行脚本的内容.这将是一个新的shell进程.它要求脚本文件本身设置可执行标志.sh myscript
)调用shell二进制文件来运行脚本,与"1"相同.- 除了不需要设置可执行标志,并且不需要使用hashbang表示第一行.唯一需要的是调用用户需要对脚本文件的读访问权.. myscript
)来调用脚本与"1"非常相似.- 表示它不是一个被调用的新shell.所有脚本的命令都在当前shell中执行,使用它的环境(并且还用它可能设置或更改的任何(新)变量"污染"它的环境.(通常这是一件非常危险的事情:但这里可能是曾经exit $RETURNVALUE
在某些条件下执行....)对于'1':
易于实现:chmod a-x myscript
将阻止myscript
直接执行.但这不会满足要求'2'.和'3.'.
为'2' 和'3.':
更难实现.通过sh myscript
要求读取
文件的权限进行调用.因此,似乎有一个显而易见的出路chmod a-r
myscript
.但是,这也会禁止'3.':您也无法获取脚本.
那么以一种使用Bashism的方式编写脚本呢?Bashism是一种特殊的方法来做其他shell不理解的事情:使用特定的变量,命令等.这可以在脚本中用来发现这种情况并对它做"做点什么"(比如"display warning.txt", "mailto admin"等).但是,除非你通过调用杀死shell,否则无法阻止sh
或者
bash
任何其他shell读取并尝试执行写入脚本的所有以下命令/行
exit
.
例如:在Bash中,通过脚本知道看到的环境$BASH
,
$BASH_ARGV
,$BASH_COMMAND
,$BASH_SUBSHELL
,BASH_EXECUTION_STRING
....如果由sh
(在a中来源sh
)调用,则执行的shell将把所有这些$BASH_*
视为空的环境变量.同样,这可以在脚本中用于发现这种情况并"做某事"...... 但不能阻止调用以下命令!
我现在假设......
#!/bin/bash
它的第一行,sh
是可用的,它是bash
或的符号链接dash
.这意味着可以使用列出的环境变量值进行以下调用
vars+invok's | ./scriptname | sh scriptname | bash scriptname | . scriptname ---------------+--------------+---------------+-----------------+------------- $0 | ./scriptname | ./scriptname | ./scriptname | -bash $SHLVL | 2 | 1 | 2 | 1 $SHELLOPTS | braceexpand: | (empty) | braceexpand:.. | braceexpand: $BASH | /bin/bash | (empty) | /bin/bash | /bin/bash $BASH_ARGV | (empty) | (empty) | (empty) | scriptname $BASH_SUBSHELL | 0 | (empty) | 0 | 0 $SHELL | /bin/bash | /bin/bash | /bin/bash | /bin/bash $OPTARG | (empty) | (empty) | (emtpy) | (emtpy)
现在您可以在文本脚本中加入逻辑:
$0
不相等-bash
,那就做一个exit $SOMERETURNVALUE
.如果脚本是通过sh myscript
或bash myscript
调用的,那么它将退出调用shell.如果它在当前shell中运行,它将继续运行.(警告:如果脚本有任何其他exit
语句,您当前的shell将被"杀死"......)
所以myscript.txt
在它的开头附近放入你的非可执行文件这样的东西可能会做一些接近你的目标:
echo BASH=$BASH
test x${BASH} = x/bin/bash && echo "$? : FINE.... You're using 'bash ...'"
test x${BASH} = x/bin/bash || echo "$? : RATS !!! -- You're not using BASH and I will kick you out!"
test x${BASH} = x/bin/bash || exit 42
test x"${0}" = x"-bash" && echo "$? : FINE.... You've sourced me, and I'm your login shell."
test x"${0}" = x"-bash" || echo "$? : RATS !!! -- You've not sourced me (or I'm not your bash login shell) and I will kick you out!"
test x"${0}" = x"-bash" || exit 33
Run Code Online (Sandbox Code Playgroud)
Jua*_*rro 15
这可能是也可能不是提问者想要的,但在类似的情况下,我想要一个脚本来表明它是来源而不是直接运行.
为了达到这个效果,我的脚本读取:
#!/bin/echo Should be run as: source
export SOMEPATH="/some/path/on/my/system"
echo "Your environment has been set up"
Run Code Online (Sandbox Code Playgroud)
因此,当我作为命令或源代码运行时,我得到:
$ ./myscript.sh
Should be run as: source ./myscript.sh
$ source ./myscript.sh
Your environment has been set up
Run Code Online (Sandbox Code Playgroud)
你当然可以通过运行脚本来欺骗脚本sh ./myscript.sh
,但至少它会在3个案例中的2个案例中给出正确的预期行为.