**已关闭。**此问题为not about programming or software development。目前不接受回答。
此问题似乎与a specific programming problem, a software algorithm, or software tools primarily used by programmers无关。如果您认为此问题与another Stack Exchange site的主题相关,可以发表评论,说明在何处可以回答此问题。
21天前关闭
Improve this question的
我遇到了一个shell脚本的问题,当从bash手动启动时,它可以正确运行,但当由crontab启动时,它不能正确运行。
结果是我打错了,用“#/bin/bash”而不是“#!/bin/bash”启动了脚本。当我从bash(“./script.sh“)手动运行它时,bash被调用来解释它。但是当脚本从crontab运行时,/bin/sh被调用了!
为什么有区别?设置了可执行位的脚本应该和二进制可执行文件一样好,那么为什么要根据它是从bash还是从crontab执行而使用不同的shell(/bin/bash vs./bin/sh)来解释它呢?我知道由于我的打字错误,脚本没有指定shell路径,但是不管哪个进程调用它,脚本都不应该使用相同的shell运行吗?
3条答案
按热度按时间myzjeezk1#
应该和二进制可执行文件一样好,那么为什么要用不同的shell(/bin/bash和/bin/sh)解释它,这取决于它是从bash还是从crontab执行?
因为它是这样被编程的。或者说是这样被标准化的。因为它应该这样做。因为历史的原因。因为它总是这样。
Linux如何决定脚本使用哪个shell?
特定于您正在使用的特定shell。下面是关于Bash shell的。任何其他shell可能会有不同的行为。
Bash shell首先尝试execve。内核然后尝试解析shebang。
如果execve失败,那么Bash如果找不到内核运行可执行文件失败的原因,就会自己检查shebang文件,然后Bash自己解析shebang文件,找出解释器并运行它。(我从this my answer复制了这一部分,这也是相关的)。
如果文件没有shebang,那么Bash会用
check_binary_file
函数检查它是否是一个二进制文件,这非常简单。然后,如果check_binary_file
也是false,那么文件内容 * 将作为bash脚本执行 *。(我经常犯的错误是忘记了python脚本中的shebang,而
import
是一个ImageMagick X11命令,它会捕获光标)。这种行为是标准的,符合规范,所有shell都是这样做的,只是它们自己运行。命令搜索和执行中的POSIX sh规范规定:
1.如果命令名至少包含一个,则shell应在单独的实用程序环境中执行该实用程序,其操作相当于调用POSIX. 1 -2017系统接口卷中定义的execl()函数,并将路径和arg 0参数设置为命令名,其余execl()参数设置为命令参数(如果有)和空终止符。
如果execl()函数由于与[ENOEXEC]错误等效的错误而失败,则shell将执行一个命令,该命令相当于以命令名作为其第一个操作数调用shell,并将任何剩余参数传递给新shell。如果可执行文件不是文本文件,则shell可能会绕过此命令执行。在这种情况下,它将写入错误消息并返回退出状态126。
bfhwhh0e2#
哈什邦
字符串
指定应该使用哪个解释器来解释文本文件。如果缺少它(并且错别字导致它丢失),系统没有任何线索并选择默认值,通常是/bin/sh
当然,系统可以尝试找出文件中使用了哪种语言。但这并不能解决问题。事实上,有些人喜欢编写可以由不同解释器解释的文本文件。如果系统发现这样的脚本,它将再次被搞砸。
更明智的方法是让开发人员决定使用哪个解释器。
g0czyy6m3#
不同行为的原因是当我交互使用bash时,SHELL环境变量被设置为/bin/bash,从而导致bash处理我的脚本。但是当我的脚本作为cron作业执行时,SHELL被设置为/bin/sh,因此存在差异。