当前位置: 首页 > 面试题库 >

在Linux和BSD中使用和不使用shebang的Bash脚本执行

冉锋
2023-03-14
问题内容

当类似Bash的脚本以二进制形式执行而没有shebang时,如何确定由谁执行?

我猜想 使用 shebang
运行普通脚本是由binfmt_script
Linux模块处理的,该模块检查shebang,解析命令行并运行指定的脚本解释器。

但是,如果有人在没有脚本的情况下运行脚本会发生什么?我已经测试了直接execv方法,发现里面没有内核魔术,即像这样的文件:

$ cat target-script
echo Hello
echo "bash: $BASH_VERSION"
echo "zsh: $ZSH_VERSION"

运行仅执行execv调用的已编译C程序将产生:

$ cat test-runner.c
void main(){
        如果(execv(“ ./ target-script”,0)== -1)
                perror();
}
$ ./测试运行器
./target-script:执行格式错误

但是,如果我从另一个shell脚本执行相同的操作,它将使用与原始脚本相同的shell解释器运行目标脚本:

$ cat test-runner.bash
#!/ bin / bash
./target-script

$ ./test-runner.bash 
你好
bash:4.1.0(1)-发布
zsh:

如果我对其他外壳(例如,Debian的默认设置sh- /bin/dash)执行相同的操作,那么它也可以工作:

$ cat test-runner.dash   
#!/ bin /破折号
./target-script

$ ./test-runner.dash 
你好
重击: 
zsh:

奇怪的是,它与zsh的配合使用效果不佳,也没有遵循一般的方案。看起来zsh /bin/sh毕竟对这样的文件执行了:

greycat @ burrow-debian〜/ z / test-runner $ cat test-runner.zsh 
#!/ bin / zsh
回声ZSH_VERSION = $ ZSH_VERSION
./target-script

greycat @ burrow-debian〜/ z / test-runner $ ./test-runner.zsh 
ZSH_VERSION = 4.3.10
你好
重击: 
zsh:

请注意,ZSH_VERSION在父脚本中有效,而ZSH_VERSION在子脚本中则无效!

如果没有shebang,shell(Bash,破折号)如何确定执行什么操作?我试图在Bash /
dash来源中挖掘该位置,但是,a,我似乎迷失了。任何人都可以阐明一种神奇的方法,这种方法确定应将没有shebang的目标文件作为脚本执行还是作为Bash
/ dash中的二进制文件执行?或者可能存在 某种互动的内核/ libc和那么我会在它是如何在Linux和FreeBSD内核/
libcs工作欢迎解释吗?


问题答案:

由于这种情况发生在破折号中,并且破折号比较简单,因此我首先看了一下。

看起来像exec.c是查找的地方,而相关的函数是tryexecshellexec只要需要执行shell指令,就会从中调用。tryexec函数(的简化版本)如下:

STATIC void
tryexec(char *cmd, char **argv, char **envp)
{
        char *const path_bshell = _PATH_BSHELL;

repeat:

        execve(cmd, argv, envp);

        if (cmd != path_bshell && errno == ENOEXEC) {
                *argv-- = cmd;
                *argv = cmd = path_bshell;
                goto repeat;
        }
}

因此,如果发生的话,它总是简单地用其自身的路径替换要执行的命令(_PATH_BSHELL默认为"/bin/sh"ENOEXEC。这里真的没有魔术。

我发现FreeBSD bash本身就表现出相同的行为sh

的方式bash处理这个问题是类似的,但要复杂得多。如果您想进一步研究它,我建议您阅读bash的内容,然后execute_command.c专门阅读execute_shell_script然后shell_execve。这些评论具有描述性。



 类似资料:
  • 问题内容: 我正在尝试执行zc.buildout自动生成的python脚本,因此我无法控制它们。我的问题是,对于bash(最多80个字符)或直接执行(某些我不知道的Linux内核常量),shebang行(#!)太长了。 这是一个示例脚本,可帮助您重现我的问题: bash或内核如何配置为允许更大的shebang行? 问题答案: 由于内核编译时间缓冲区的限制,在99.9%的系统上限制为127个字符。

  • 问题内容: 当应该从python运行脚本时 ,文件的正确Shebang是什么? 作为示例测试用例,尚未安装我的系统(OSX)上的默认python 。pyenv virtualenv可以。我试图从virtualenv获取python可执行文件的路径。 所以我举了一个例子: 但是,当我尝试运行脚本时,出现错误: 尽管在命令行上运行该路径可以正常工作: 什么是适当的shebang?理想情况下,我想要一些

  • 我正在尝试创建一个bash脚本,它允许我在每次执行它时扩展路径。下面是我要指出的代码: 当我运行它并且cmd请求一个新目录时,我输入了我想要添加的目录,但它显示“第6行:路径:未找到命令” 欢迎所有建议,提前感谢。

  • 目录表 Linux和BSD用户 Windows®用户 概括 Linux和BSD用户 如果你正在使用一个Linux的发行版比如Fedora或者Mandrake或者其他(你的选择),或者一个BSD系统比如FreeBSD,那么你可能已经在你的系统里安装了Python。 要测试你是否已经随着你的Linux包安装了Python,你可以打开一个shell程序(就像konsole或gnome-terminal)

  • 问题内容: 是否可以在Linux和Mac上调用无需备份的待办事情就地编辑?虽然似乎需要OS X附带的BSD ,但是GNU Linux发行版通常随附将引号解释为空的输入文件名(而不是备份扩展名),而是需要使用引号。 是否有任何两种语法都适用的命令行语法,所以我可以在两个系统上使用相同的脚本? 问题答案: 如果您真的只想使用“简单”的方法,那么以下DOES可以在GNU和BSD / Mac上运行: 注意

  • 问题内容: 的 备用屏幕 用于通过像vim,HTOP,屏幕,alsamixer中,以下,…它像一个不同缓冲液中的终端的内容的,其消失的应用程序退出时,所以整个终端许多“用户交互式”应用终端恢复后,看起来应用程序没有输出任何东西。 我想在自己的shell(bash)脚本中实现完全相同的功能,除了它不必具有可移植性。我只会使用linux和基于xterm的终端仿真器;但解决方案应尽可能使用类似的方法。但