web-dev-qa-db-ja.com

シバンで環境変数を使用するにはどうすればよいですか?

私はPythonスクリプトを特定のpythonインストールで実行する必要があります。Shebangを作成して_$FOO/bar/MyCustomPython_?

36
eric.frederich

シバン線は非常に限られています。多くのUNIXバリアント(Linuxを含む)では、コマンドと単一の引数の2つの単語しか持てません。多くの場合、長さに制限があります。

一般的な解決策は、小さなシェルラッパーを記述することです。 Pythonスクリプトにfoo.pyという名前を付け、foo.pyの横にシェルスクリプトを置き、fooと名前を付けます。このアプローチでは、Pythonスクリプトに特定のヘッダーは必要ありません。

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

別の魅力的なアプローチは、上記のようなラッパースクリプトを記述し、Pythonスクリプトのシバン行として#!/path/to/wrapper/scriptを配置することです。ただし、ほとんどのuniceはShebangスクリプトのチェーンをサポートしていないため、これは機能しません。

MyCustomPython$PATHに含まれている場合は、envを使用して検索できます。

#!/usr/bin/env MyCustomPython
import …

さらに別のアプローチは、スクリプトが有効なシェルスクリプト(適切な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で同じ効果を実現する1つの方法を次に示します。シェルでは、"true"trueユーティリティであり、その引数(2つの1文字の文字列:および')を無視し、true値を返します。 Pythonでは、"true"はブール値として解釈されるとtrueになる文字列であるため、これは常にtrueで文字列リテラルを実行するif命令です。

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

ロゼッタコードには、他のいくつかの言語でこのような2言語のスクリプトがあります。

シバン行は変数の展開を受けないため、ドル[F-O-O -...という名前の実行可能ファイルを検索するため、$FOO/MyCustomPythonを使用できません。

もう1つの方法は、Shebangにインタープリターとしてのシェルスクリプトをポイントさせることです。このシェルスクリプトは、環境変数を使用して正しい変数を特定し、実行することができます。

例:mypython.sh(または/usr/local/bin上のその他のディレクトリ)に$PATHスクリプトを作成し、次の内容を含めます。

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

次に、このShebang行を使用して、mypython.shを介してMyCustomPythonからPythonスクリプトを実行させることができます。

#!/usr/bin/env mypython.sh
12
Riccardo Murri

カスタムのpythonインストールへの絶対パスを使用するか、$PATHに入れて#!/usr/bin/env [command]を使用できます。それ以外の場合は、ラッパーを記述して例として、execを使用してプロセスイメージを置き換えます。

#!/bin/bash
exec "$ENV/python" "$@"
4
Chris Down

まず、Pythonのバージョンが標準のPythonすでにインストールされている(たとえば、追加モジュール))とどのように異なるかを確認し、次にプログラムの開始時にPythonの呼び出し方法を「切り替える」:

#!/usr/bin/python
import os
import sys
try:
    import MyCustomModule
except ImportError:
    # only need to use expandvar if you know the string below has an envvar
    custprog = os.path.expandvar("$FOO/bar/MyCustomPython")
    os.execv(custprog, sys.argv) # call alternate python with the same arguments
    raise SystemExit('could not call %s' % custprog)
# if we get here, then we have the correct python interpreter

これにより、他のPythonのインスタンスからプログラムを呼び出すことができます。システムのpythonにモジュールとしてインポートできない、組み込みのSQLライブラリを持つインスタンスについても同様のことを行います。

3
Arcege

$FOO$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
0
chan