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


46

如果我要执行未设置执行许可的bash脚本,则可以执行以下操作:

bash script.sh

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


机智打击有什么问题?
steffen

@steffen您怎么知道有问题的文件是bash脚本?
muru

@muru引用问题:“如果我想执行bash脚本...”而且(即使它不是bash脚本),如果bash whatever可行,为什么还要使用其他方法?bash实际上在每个* ix系统上都可用,所以为什么要打扰...
steffen

1
@steffen您是否阅读了其余的问题?他们说:“如果……那么我可以做:……”和“如果…… 我不知道正确的解释器,我应该用什么代替bash ?”
muru

@muru:也许我看不到明显的东西。但是,如果文件/ has /有一个shebang行,如问题中所述,bash会完全按照要求进行操作。就像perl一样,根据下面的答案。那么不使用bash有什么好处呢?
steffen

Answers:


67

是的 它叫做perl

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会将程序分派给正确的解释器。


40
好吧,那太脏了。
2016年

1
文件扩展名.js也可以吗?
Pysis

1
另外,什么机器不做#!。我现在似乎更多了,还没有遇到这个问题。
Pysis

1
好吧,这只是你的例子似乎凸显了大量的文件扩展名,而不是展示一些家当线文件,我想我以为这就是它的预测是如何工作的。
Pysis

2
我喜欢man perlrun令人毛骨悚然地承认它“有点奇怪” :)。我认为这应视为针对非UNIX环境和非常老版本的UNIX 的好奇心。
2016年

25

剧本不一定会有shebang

如果脚本是从解释器中运行,你不能确保它具有家当脚本,从解释器中运行不需要家当如果你调用解释器来运行代码。

因此,答案是否定的,没有命令可以确定使用哪种语言(解释器)来运行脚本。但是,您始终可以查看脚本的内部,看看是否有需要查找的脚本。

简要的规则:

  1. 当您运行脚本时,调用解释器总是会否决可能的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脚本上调用(测试)正确的解释器。

说明

  • 该脚本仅读取脚本的第一行,将其删除,#!然后使用其余的来调用解释器。
  • 如果无法调用有效的解释器,它将引发a PermissionError或a FileNotFoundError

注意

扩展(.sh.py等等)凡在确定Linux上的适当的解释没有任何作用。


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


好的,这意味着尽管Linux在某处实现了shebang提取(以便它可以为可执行的脚本选择正确的解释器),但它不是作为独立的标准命令提供的。
艾瓦尔(Aivar)

@Aivar提取shebang并不是问题,但是在没有它的情况下运行代码是完全可能的。
雅各布·弗利姆

@Aivar啊,我明白你的意思了。如果脚本是可执行的并且在命令中没有语言运行,则脚本将调用解释器,而不是相反。
雅各布·弗利姆

1
@JacobVlijm我不会说“脚本调用解释器”,更像是“ Linux内核使用shebang行来确定执行脚本时要调用哪个解释器”。
圣保罗Ebermann

@PaŭloEbermann谢谢!当然是这样。内核以任何一种方式处理整个过程,但是从形象上讲,我认为更好地理解是说“允许”脚本处理要调用的解释器(实际上是这样做的)。不确定措词,但我想将其描述为主动权在脚本上,而内核实际上在工作。
雅各布·弗利姆

6

您可以使用如下脚本来实现:

#!/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)。从根本上讲,直接调用脚本的过程并不了解#!-内核使用它来确定需要启动解释器。


2
我一直认为这是外壳程序的功能,而不是内核的功能。今天学到了新东西。
boatcoder

1
@boatcoder-感兴趣的人,可以添加指向Linux源代码处理位置的链接。
2016年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.