是否有一个命令可以根据脚本的 shebang 行来运行该脚本?

是否有一个命令可以根据脚本的 shebang 行来运行该脚本?

如果我想执行一个没有设置执行权限的 bash 脚本,我可以这样做:

bash script.sh

bash如果脚本不可执行,而且我不知道正确的解释器,我应该用什么来代替?是否有命令可以从 shebang 行查找解释器并使用它执行脚本?

答案1

是的。它被称为perl。以下是一些示例,其中相应的解释器位于文件的 shebang 行中(实际文件扩展名无关紧要):

perl foo.bash    # works
perl foo.lua     # works
perl foo.clisp   # works
perl foo.csh     # works
perl foo.php     # works
perl foo.gnuplot # works (no arguments)
perl foo.pl      # works (obviously)
perl foo.py      # works
perl foo.sh      # works
perl foo.tcl     # works
perl foo.rb      # works
perl foo.nodejs  # works
perl foo.r       # works
perl foo.oct     # works
perl foo.csharp  # works (no arguments)

这在Perl 的文档

如果该#!行不包含单词“perl”或单词“indir”,则将#!执行以 命名的程序,而不是 Perl 解释器。这有点奇怪,但它可以帮助那些没有 的机器上的人们#!,因为他们可以告诉程序他们的 SHELL 是 /usr/bin/perl,然后 Perl 会将程序分派到正确的解释器。

答案2

脚本不一定有shebang

如果脚本是从解释器运行的,你就不能确定它是否根本从解释器运行的脚本不需要 shebang如果你调用解释器来运行代码。

因此答案是否定的,没有命令可以确定运行脚本的语言(解释器)。不过,你总是可以查看脚本内部,看看它是否有可以找出答案的东西。

规则简述:

  1. 运行脚本时,调用解释器总是否决可能的 shebang,无论是否可执行,无论是否是 shebang。
  2. 如果不可执行则运行解释器、脚本不需要shebang。
  3. 如果脚本在运行前没有先调用解释器,它需求(并使用)shebang 来找出要调用哪个解释器,它需要是可执行的才能具有从其shebang调用解释器的“权限”。

但是,如果脚本没有 shebang,则脚本内部就没有(直接*)信息来告诉要使用哪个解释器。

话说回来

当然,你也可以编写一个包装脚本来尝试找出脚本是否有shebang并从中读取解释器,然后从找到的解释器运行它。

一个例子

#!/usr/bin/env python3
import subprocess
import sys

args = sys.argv[1:]; script = args[0]

try:
    lang = open(script).readlines()[0].replace("#!", "").strip().split()[-1]
    cmd = [lang, script]+args[1:]
    subprocess.call(cmd)
except (PermissionError, FileNotFoundError, IndexError):
    print("No valid shebang found")
  • 将其保存为tryrun$PATH例如~/bin,如果目录不存在,则创建目录,注销并重新登录),将其创建可执行文件.然后运行:

    tryrun /path/to/nonexecutablescript
    

    在我的不可执行文件pythonbash脚本上调用(测试)正确的解释器。

解释

  • 该脚本只是读取脚本的第一行,删除#!并使用其余部分来调用解释器。
  • 如果无法调用有效的解释器,它将引发PermissionErrorFileNotFoundError

笔记

扩展名(.sh.py等)在确定 Linux 上适当的解释器时不起任何作用。


(*当然可以开发一种“智能”猜测算法来从代码中确定语法。)

答案3

您可以使用如下脚本实现此目的:

#!/bin/bash

copy=/tmp/runner.$$
cp $1 ${copy}
chmod u+x ${copy}
${copy}
rm ${copy}

因此:

$ echo "echo hello" > myscript
$ ./myscript
bash: ./myscript: Permission denied
$ ./runscript myscript 
hello

我不建议这样做。权限的存在是有原因的。这是一个破坏权限的程序。

请注意,shebang 处理是核心函数(在 Linux 源代码中 -fs/binfmt_script.c)。从根本上来说,直接调用脚本的进程并不知道#!——内核会使用它来确定是否需要启动解释器。

相关内容