Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Shell 检测脚本是否来源于“/bin/sh”_Shell_Sh_Freebsd - Fatal编程技术网

Shell 检测脚本是否来源于“/bin/sh”

Shell 检测脚本是否来源于“/bin/sh”,shell,sh,freebsd,Shell,Sh,Freebsd,我在这里找到的大多数答案似乎只适用于/bin/bash 像$BASH_SOURCE和$SHLVL这样的技巧似乎对sh不起作用 有一个答案要求使用return,因为它只在函数和源代码脚本中工作,并查看它是否生成任何错误,但我不明白为什么在命令行上执行return时,我从shell中注销了。如果我执行或获取了包含return的脚本,它就会退出该脚本。这是在我使用freebsd时发生的。我也不使用任何桌面环境 只需在命令行上键入 return 结果:注销 执行或寻源包含返回的脚本: 当我第一次在ma

我在这里找到的大多数答案似乎只适用于/bin/bash

像$BASH_SOURCE和$SHLVL这样的技巧似乎对sh不起作用

有一个答案要求使用return,因为它只在函数和源代码脚本中工作,并查看它是否生成任何错误,但我不明白为什么在命令行上执行return时,我从shell中注销了。如果我执行或获取了包含return的脚本,它就会退出该脚本。这是在我使用freebsd时发生的。我也不使用任何桌面环境

只需在命令行上键入

return
结果:注销

执行或寻源包含返回的脚本:

当我第一次在macOSexecuted/bin/sh上执行相同操作时,情况并非如此。它在那里工作得非常好。上面说

sh:return:只能从函数或源脚本“返回”

正如所料

我正在寻找一种解决方案来检测脚本是否源于/bin/sh

我使用的是freebsd,目前我的默认shell设置为sh。我知道我可以安装bash,但我仍然想知道如何对/bin/sh执行相同的操作

更新: 我想再提一点细节

马科斯 在macOS中,我尝试通过命令行启动/bin/sh,后来我意识到它是一个非登录shell。所以,当我在那里输入注销时,reusult是:

sh:注销:非登录shell:使用“退出”

因此,我将/bin/sh作为默认shell,并且我确信/bin/sh已被执行。当我在那里输入return时,我得到的输出是:

sh:return:只能从函数或源脚本“返回”

又如所料。但当我输入echo$SHELL时,输出是:

/bin/bash

我检查了我机器的/bin目录,/bin/sh和/bin/bash似乎没有链接

FreeBSD 现在我也尝试在那里执行/bin/sh。结果如下:

$ /bin/sh
$ return
$ return
logged out on 2nd return
因此,在简单语言中,如果/bin/sh是非登录shell,并且只是退出该shell,则不会显示任何输出

@user1934428在@CharlesDuffy的回答中提供了大量的信息。值得一读

在那个里,他提到FreeBSD手册并没有返回语句的文档。

我检查了OpenBSD对手册页的大小写是否相同,但它确实将return定义为:

返回[n]退出当前函数或。退出状态为n的脚本,或执行的最后一个命令的脚本

另一个问题是,大多数手册页都会显示bash手册中关于询问mansh.Idk是否应该这样的问题

另外,有人能建议我是否应该针对未定义的回报行为开始一个新问题吗?因为我觉得这个问题太离题了。不确定这样做是否是个好主意。

$sh./detect-sourcing.sh 我们被处决了 $sh-c'/检测来源。sh' 我们被找到了
我还没有分析POSIX sh标准是否严格要求这一点,但它与MacOS上的/bin/sh(OP)配合使用。

我从中找到了答案

缺少返回条目的手册页是错误的手册页

从正确的角度来看,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:


并将其与名称匹配。如果扩展生成了其他内容,则意味着脚本已经获得了源代码。另一种情况可能是用户将其重命名。所以它不太容易出错,但仍然应该完成我的工作。

如果您计划使用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外壳的工作原理如手册第sh1页所述。 在MacOS中,虽然文件/bin/sh和/bin/bash略有不同,但/bin/sh基本上是bash。
请注意,Mac上的comand man sh为bash带来了手册页

这个答案如何:?@Moby04,阅读该答案中的注释。还有来自@mklement0的更详细的答案呢?如果您从终端cmd行获取脚本,而不包括执行的return调用,它将在任何shell中注销您。我几乎可以肯定。这与从cmd行或cron或???运行脚本不同,它源于返回的脚本。这将返回cmd行。祝你好运。@user1934428 bash在任何系统上都是从GNU源代码构建的,但BSD和Linuxes有一个单独的sh手册页。POSIX中的结果未指明:如果我的问题不清楚,我道歉,我会在拿到笔记本后立即编辑它。我的平台是freebsd,在这里它显示了意外的结果。我在macOS上也做了同样的测试,一切正常。明白了。不幸的是,我不知道POSIX标准要求任何地方存在可检测的行为差异,因此除非其他人能够找到这一点,否则我们将
需要重新调谐以发现FreeBSD的实现与苹果的实现之间的差异。这仍然是为什么在交互式shell中返回终止它的原因。有趣的是,这个函数甚至没有提到return语句,例如ash的手册页,它应该非常接近sh,加上只在函数内部定义return的效果,所以它在函数外部的作用似乎是未指定的行为。有些离题,但是可能很有趣:zsh定义了返回的效果,至少对于它在trap语句中的使用也是如此,但是对于它在交互提示中的使用也是沉默的。尝试一下,对于我的zsh 5.5.1,返回不会终止当前shell。bash也不会让我退出,而ash和dash会。对我来说,看起来有点过分了。如果脚本是使用完整路径执行的,为什么要删除路径名?我认为这不管用。假设脚本t1源于另一个脚本t2。在t2中检查$0将反映t1是如何被调用的,因为在t2运行时它没有被更改。@jhnc,我的错,我太懒了,没有在邮件列表中写出完整的解释。我更新了我的答案。这是因为,如果一个脚本知道它被调用什么,我们将它的名称与${0*/}匹配,但它不匹配,这就意味着该脚本已经获得了源代码。Ofc这并不是万无一失的,但与其他方法相比,这种方法失败的情况似乎要少一些。@YuriGinsburg,我们无法知道脚本是从什么路径执行的。但脚本名称更改的情况仍然较少。因此,如果脚本名和${0*/}不匹配,则表示它已被源代码化。如上所述,它不是完全无错误的,但仍然有较少的机会导致错误。@Mihir源代码的脚本在$0和${0*/}中只有sh,我们将结果与此进行比较。但是对于已执行的脚本,比如/home/user/bin/sh,$0将生成完整路径,${0*/}just sh–与源代码脚本相同。我认为如果从另一个脚本t2内部调用t,这不起作用$0保留t2中的值,并将反映t2是如何被调用的。@jhnc是正确的,但macos上的yea man sh生成man bash
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.
${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