如何在我的shebang中使用环境变量?

eri*_*ich 38 python executable shell-script

我有一个需要使用特定 python 安装运行的 Python 脚本。有没有办法制作一个shebang以便它运行$FOO/bar/MyCustomPython

Gil*_*il' 30

shebang线非常有限。在许多 unix 变体(包括 Linux)下,您只能有两个词:一个命令和一个参数。通常也有长度限制。

一般的解决方案是编写一个小的 shell 包装器。命名 Python 脚本foo.py,并将 shell 脚本放在旁边foo.py并调用它foo。这种方法不需要 Python 脚本上的任何特定标头。

#!/bin/sh
exec "$FOO/bar/MyCustomPython" "$0.py" "$@"
Run Code Online (Sandbox Code Playgroud)

另一种诱人的方法是编写一个像上面那样的包装器脚本,并将其#!/path/to/wrapper/script作为 Python 脚本的 shebang 行。然而,大多数 unices 不支持 shebang 脚本的链接,所以这行不通。

如果MyCustomPython在 中$PATH,您可以使用env它来查找:

#!/usr/bin/env MyCustomPython
import …
Run Code Online (Sandbox Code Playgroud)

另一种方法是将脚本安排为有效的 shell 脚本(它自己加载正确的 Python 解释器)和目标语言(这里是 Python)中的有效脚本。这要求您找到一种方法来为您的目标语言编写这样的双语脚本。在 Perl 中,这称为if $running_under_some_shell.

#!/bin/sh
eval 'exec "$FOO/bar/MyCustomPerl" -wS $0 ${1+"$@"}'
    if $running_under_some_shell;
use …
Run Code Online (Sandbox Code Playgroud)

这是在 Python 中实现相同效果的一种方法。在 shell 中,"true"true实用程序,它忽略其参数(两个单字符串:')并返回一个真值。在 Python 中,"true"是一个字符串,当解释为布尔值时为真,因此这是一条if始终为真并执行字符串文字的指令。

#!/bin/sh
if "true" : '''\'
then
exec "$FOO/bar/MyCustomPython" "$0" "$@"
exit 127
fi
'''
import …
Run Code Online (Sandbox Code Playgroud)

Rosetta 代码在其他几种语言中有这样的双语言脚本。


Ric*_*rri 12

Shebang 行不会进行变量扩展,因此您不能使用$FOO/MyCustomPython它,因为它会搜索名为 Dollar-FOO-...

另一种方法是让你的shebang指向一个shell脚本作为解释器,然后这个shell脚本可以使用环境变量来定位正确的并执行它。

示例:mypython.sh/usr/local/bin(或您的 上的任何其他目录$PATH)中创建一个脚本,内容如下:

#! /bin/sh
PYTHON="$FOO/bar/MyCustomPython"
exec "$PYTHON" "$@"
Run Code Online (Sandbox Code Playgroud)

然后您可以使用此shebang行MyCustomPython通过mypython.sh以下方式执行Python脚本:

#!/usr/bin/env mypython.sh
Run Code Online (Sandbox Code Playgroud)

  • 使用`$python`,而不是`$PYTHON` -- 按照惯例,我们将环境变量(PAGER、EDITOR、SHELL ...脚本中的`$PYTHON` 不是环境变量)和内部shell 变量(BASH_VERSION、RANDOM)大写,……)。所有其他变量名称应至少包含一个小写字母。此约定可避免意外覆盖环境和内部变量。此外,不要为您的脚本使用扩展名。脚本定义了您可以运行的新命令,并且命令通常没有扩展名。 (6认同)