是否有根据其shebang行运行脚本的命令?

Aiv*_*var 47 command-line scripts executable shebang

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

bash script.sh
Run Code Online (Sandbox Code Playgroud)

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

Ole*_*nge 73

是的。它被称为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)
Run Code Online (Sandbox Code Playgroud)

Perl 的文档中提到了这一点:

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

  • 嗯,那只是脏。 (45认同)
  • 我喜欢 `man perlrun` 如何羞怯地承认它“有点奇怪”:)。我认为这应该被视为针对非 UNIX 环境和非常*非常* 旧版本的 UNIX 的好奇心。 (4认同)

Jac*_*ijm 25

脚本不一定有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")
Run Code Online (Sandbox Code Playgroud)
  • 将其保存为tryrunin $PATH(例如~/bin,如果目录不存在,则创建该目录,注销并重新登录),使其可执行。然后运行:

    tryrun /path/to/nonexecutablescript
    
    Run Code Online (Sandbox Code Playgroud)

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

解释

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

笔记

扩展(.sh.py等)中扮演的角色没有任何确定在Linux上适当的解释。


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


sli*_*lim 6

您可以使用这样的脚本来实现这一点:

#!/bin/bash

copy=/tmp/runner.$$
cp $1 ${copy}
chmod u+x ${copy}
${copy}
rm ${copy}
Run Code Online (Sandbox Code Playgroud)

因此:

$ echo "echo hello" > myscript
$ ./myscript
bash: ./myscript: Permission denied
$ ./runscript myscript 
hello
Run Code Online (Sandbox Code Playgroud)

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

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

  • 我一直认为这是 shell 的函数,而不是内核的函数。今天学到了新东西。 (2认同)