我在这里发现的最常见答案仅是/bin/bash
。
$BASH_SOURCE
和$SHLVL
之类的技巧似乎不适用于sh
。
有一个要求使用return
的答案,因为它仅在函数和源脚本中起作用,并查看它是否产生任何错误,但我不明白为什么在命令上执行return
-line我退出了shell。如果我“执行或获取”包含return
的脚本,它将退出该脚本。这是我在freebsd
上时发生的。另外,我在那里不使用任何桌面环境。
只需在命令行上输入
return
结果:已注销
执行或获取包含return
的脚本:
$ cat testscript
#! /bin/sh
echo hello
return
echo hello
$ ./testscript
hello
$ . testscript
hello
$
当我在macOS
(首先执行/ bin / sh)上执行相同操作时,情况并非如此。在那里工作得很好。那里只是说
sh:return:只能从函数或源脚本中“返回”
与预期的一样。
我正在寻找一种解决方案,以检测在/bin/sh
情况下脚本是否为源。
我正在使用freebsd
,目前我的默认shell设置为sh
。我知道我可以安装bash
,但是我仍然想知道如何为/bin/sh
做同样的事情。
我想提一点细节。
在macOS
中,我尝试通过命令行启动/bin/sh
,后来我意识到它是一个非登录shell。因此,当我在此处输入logout
时,结果是:
sh:注销:不登录shell:使用`exit'
因此,我将/bin/sh
设置为默认外壳程序,并且确信执行了/bin/sh
。当我在此处输入return
时,我得到的输出是:
sh:return:只能从函数或源脚本中“返回”
再次达到预期。但是当我输入echo $SHELL
时,输出为:
/ bin / bash
然后我检查了机器的/bin
目录,而/bin/sh
和/bin/bash
似乎没有链接。
现在我也尝试在那里执行/bin/sh
。结果如下:
$ /bin/sh
$ return
$ return
logged out on 2nd return
因此,如果/bin/sh
是非登录外壳程序,并且仅退出该外壳程序,那么用简单的语言就不会显示任何输出。
@ user1934428在@CharlesDuffy的答案中提供了很多信息。值得一读。
他提到FreeBSD
手册中没有return
声明的文档。
sh man page, FreeBSD
我检查了OpenBSD的手册页是否具有相同的大小写,但是确实将return
定义为:
返回[n]退出当前功能或。退出状态为n或最后执行的命令的脚本。
另一个问题是,大多数手册页都在bash
手册中显示有关man sh
的要求。如果它应该是那样或否,则为Idk。
还可以有人建议我为return
的不确定行为提出一个新问题吗?因为我认为这个问题已经脱离话题了。不确定这样做是否是个好主意。
答案 0 :(得分:3)
$ sh ./detect-sourcing.sh
We were executed
$ sh -c '. ./detect-sourcing.sh'
We were sourced
#!/bin/sh
if (return 2>/dev/null); then
echo "We were sourced"
else
echo "We were executed"
fi
我还没有分析POSIX sh标准是否严格要求这样做,但是它可以在OS的stated platform的MacOS上与/bin/sh
一起使用。
答案 1 :(得分:0)
我通过FreeBSD mailing lists找到了答案。
缺少return
条目的手册页是错误的手册页。
看看正确的man page,已经说明了return
语句的完整行为。
The syntax of the return command is
return [exitstatus]
It terminates the current executional scope, returning from the closest
nested function or sourced script; if no function or sourced script is
being executed, it exits the shell instance. The return command is im-
plemented as a special built-in command.
如伊恩(Ian)在邮件列表中所建议的那样,对于/bin/sh
,一种好方法似乎是为脚本保留一个固定名称并展开$0
:
${0##*/}
,然后将其与名称匹配。如果扩展产生了其他任何内容,则表示脚本已获得源。另一种情况是用户将其重命名。因此,它并非完全容易出错,但仍然应该完成我的工作。
答案 2 :(得分:0)
如果您打算使用Bourne shell(/ bin / sh),仅测试$ 0会很好。
$ cat t
#!/bin/sh
if [ $0 == "sh" ]; then
echo "sourced"
else
echo executed
fi
$ . t
sourced
$ . ./t
sourced
$ ./t
executed
$ sh t
executed
$ sh ./t
executed
如果要从其他shell调用或获取脚本,请针对shell名称列表测试$ 0。
正如@Mihir所指出的那样,FreeBSD shell的工作方式如手册页sh(1)中所述。 在MacOS中,/ bin / sh基本上是bash,尽管文件/ bin / sh和/ bin / bash略有不同。 请注意,在Mac上,comand man sh为bash带来了手册页