当前位置: 首页>>技术教程>>正文


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

, , , ,

问题描述

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

bash script.sh

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

最佳解决方案

是的。它叫做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’s documentation中提到:

If the #! line does not contain the word “perl” nor the word “indir”, the program named after the #! is executed instead of the Perl interpreter. This is slightly bizarre, but it helps people on machines that don’t do #! , because they can tell a program that their SHELL is /usr/bin/perl, and Perl will then dispatch the program to the correct interpreter for them.

次佳解决方案

脚本不一定有一个shebang

如果脚本是从解释器运行的,那么你无法确定它是否具有shebang。如果您调用解释器来运行代码,则从解释器运行的脚本不需要shebang。

答案是否定的,没有命令可以确定运行脚本的语言(解释器)是什么。但是,您可以随时查看脚本内部,看看它是否有shebang可以查找。

简而言之:

  1. 当你运行脚本时,调用解释器总是否决可能的shebangs,可执行与否,shebang与否。

  2. 如果不可执行并从解释器运行,脚本不需要shebang。

  3. 如果脚本在没有首先调用解释器的情况下运行,它需要(并使用)shebang来找出要调用的解释器,并且需要可执行以使”permission”从其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")
  • 将它保存为$ PATH中的tryrun(例如〜/bin,如果目录不存在则生成目录,注销并重新登录),使其可执行。然后运行:

    tryrun /path/to/nonexecutablescript
    

    在我的non-executable pythonbash脚本上调用(测试)了正确的解释器。

Explanation

  • 该脚本只是读取脚本的第一行,删除#!并使用其余的来调用解释器。

  • 如果它无法调用有效的解释器,它将引发PermissionErrorFileNotFoundError

说明

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


(*当然可以开发一个”smart”猜测算法来确定代码的语法。)

第三种解决方案

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

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

参考资料

本文由Ubuntu问答整理, 博文地址: https://ubuntuqa.com/article/1714.html,未经允许,请勿转载。