Relative shebang: How to write an executable script running portable interpreter which comes with it

这一生的挚爱 提交于 2019-12-06 05:40:05

问题


Let's say we have a program/package which comes along with its own interpreter and a set of scripts which should invoke it on their execution (using shebang).

And let's say we want to keep it portable, so it remains functioning even if simply copied to a different location (different machines) without invoking setup/install or modifying environment (PATH). A system interpreter should not be mixed in for these scripts.

The given constraints exclude both known approaches like shebang with absolute path:

#!/usr/bin/python 

and search in the environment

#!/usr/bin/env python

Separate launchers look ugly and are not acceptable.

I found good summary of the shebang limitations which describe why relative path in the shebang are useless and there cannot be more than one argument to the interpreter: http://www.in-ulm.de/~mascheck/various/shebang/

And I also found practical solutions for most of the languages with 'multi-line shebang' tricks. It allows to write scripts like this:

#!/bin/sh
"exec" "`dirname $0`/python2.7" "$0" "$@"
print copyright

But sometimes, we don't want to extend/patch existing scripts which rely on shebang with an absolute path to interpreter using this approach. E.g. Python's setup.py supports --executable option which basically allows to specify the shebang content for the scripts it produces:

python setup.py build --executable=/opt/local/bin/python

So, in particular, what can be specified for --executable= in order to enable the desired kind of portability? Or in other words, since I'd like to keep the question not too specific to Python...

The question

How to write a shebang which specifies an interpreter with a path which is relative to the location of the script being executed?


回答1:


The relative path written directly in a shebang is treated relative to the current working directory, so something like #!../bin/python2.7 will not work for any other working directory except few.

Since OS does not support it, why not to use external program like using env for PATH lookup. But I know no specialized program which computes the relative paths from arguments and executes the resulting command.. except the shell itself and other scripting engines.

But trying to compute the path in a shell script like

#!/bin/sh -c '`dirname $0`/python2.7 $0'

does not work because on Linux shebang is limited by one argument only. And that suggested me to look for scripting engines which accept a script as the first argument on the command line and are able to execute new process:

Using AWK

#!/usr/bin/awk BEGIN{a=ARGV[1];sub(/[a-z_.]+$/,"python2.7",a);system(a"\t"ARGV[1])}

Using Perl

#!/usr/bin/perl -e$_=$ARGV[0];exec(s/\w+$/python2.7/r,$_)


来源:https://stackoverflow.com/questions/33225082/relative-shebang-how-to-write-an-executable-script-running-portable-interpreter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!