问题描述
如果我想执行一个没有设置执行权限的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可以查找。
简而言之:
-
当你运行脚本时,调用解释器总是否决可能的shebangs,可执行与否,shebang与否。
-
如果不可执行并从解释器运行,脚本不需要shebang。
-
如果脚本在没有首先调用解释器的情况下运行,它需要(并使用)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
python
和bash
脚本上调用(测试)了正确的解释器。
Explanation
-
该脚本只是读取脚本的第一行,删除
#!
并使用其余的来调用解释器。 -
如果它无法调用有效的解释器,它将引发
PermissionError
或FileNotFoundError
。
说明
扩展(.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
)。从根本上说,直接调用脚本的过程不知道#!
– 内核使用它来确定它需要启动解释器。