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

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

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

答案1

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

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

#!/bin/sh
exec "$FOO/bar/MyCustomPython" "$0.py" "$@"

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

如果MyCustomPython在 中$PATH,您可以使用env以下方式查找:

#!/usr/bin/env MyCustomPython
import …

另一种方法是将脚本安排为既有效的 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 …

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

#!/bin/sh
if "true" : '''\'
then
exec "$FOO/bar/MyCustomPython" "$0" "$@"
exit 127
fi
'''
import …

Rosetta 代码具有多种其他语言的双语言脚本。

答案2

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

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

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

#! /bin/sh
PYTHON="$FOO/bar/MyCustomPython"
exec "$PYTHON" "$@"

MyCustomPython那么你可以使用这个 shebang 行通过via执行 Python 脚本mypython.sh

#!/usr/bin/env mypython.sh

答案3

您可以使用自定义 python 安装的绝对路径,也可以将其放入您的$PATH并使用#!/usr/bin/env [command].否则,为其编写一个包装器并用于exec替换过程映像,例如:

#!/bin/bash
exec "$ENV/python" "$@"

答案4

如果您可以将$FOOin替换$FOO/bar/MyCustomPython为具体路径选项,则可以通过直接在其中env设置自定义来告诉 shebang 行在哪里查找您的自定义 Python 版本。PATH

#!/usr/bin/env PATH="/path1/to/MyCustomPython:/path2/to/MyCustomPython" python

编辑:似乎只有在 PATH 值分配周围没有引号的情况下才有效:

#!/usr/bin/env PATH=/path1/to/MyCustomPython:/path2/to/MyCustomPython python

相关内容