
#!/path/to/NAME
私は他の人から得たいくつかのスクリプトにshebangsがあり、他のスクリプト(同じツールNAMEを使用)にはshebangsがあることがわかりました#!/usr/bin/env NAME
。
どちらもうまくいくようです。チュートリアル(Pythonチュートリアルなど)では、後者がより良いと提案されているようです。しかし、なぜこれが起こるのかよく理解していません。
後者のshebangを使用するには、NAMEがPATHになければなりませんが、最初のshebangにはこの制限がないことに気づきました。
また、(私にとっては)最初のものがNAMEの場所を正確に指定するので、より良いShebangのようです。したがって、この場合、NAMEの複数のバージョン(例:/usr/bin/NAME、/usr/local/bin/NAME)がある場合、最初のケースでは使用されるバージョンを指定します。
私の質問は、最初のshebangが2番目のshebangよりも優れている理由は何ですか?
答え1
これは必ずしも良いわけではありません。
利点#!/usr/bin/env python
は、python
ユーザーの$PATH
。
これダメージその#!/usr/bin/env python
理由は、python
ユーザーの$PATH
。
これは、スクリプトを実行している人によってスクリプトが異なる動作をする可能性があることを意味します。ユーザーの場合は、/usr/bin/python
オペレーティングシステムと一緒にインストールされているものを使用できます。一方、うまく/home/phred/bin/python
機能しない実験を使用することもできます。
python
のみインストールされている場合、/usr/local/bin
in/usr/local/bin
を持たないユーザーは$PATH
スクリプトを実行することもできません。 (これは最新のシステムでは不可能かもしれませんが、より曖昧なソルバーでは簡単に発生する可能性があります。)
指定すると、#!/usr/bin/python
スクリプトの実行に使用するインタプリタを正確に指定できます。特定のシステムで。
もう一つの潜在的な問題はこの#!/usr/bin/env
トリックです。インタプリタに引数を渡すことはできません。(暗黙的に渡されたスクリプト名を除く)通常問題ではありませんが、問題かもしれません。多くのPerlスクリプトがで書かれていますが、#!/usr/bin/perl -w
今ではuse warnings;
代わりにお勧めします。 Cshスクリプトは -- を使用する必要が#!/bin/csh -f
ありますが、cshスクリプトは推奨しない最初。ただし、他の例があるかもしれません。
新しいシステムにアカウントを設定するときに、パーソナルソース管理システムに複数のPerlスクリプトをインストールしました。私は各スクリプトを#!
私$HOME/bin
。#!/usr/bin/perl
小さな点:この#!/usr/bin/env
トリックはコマンドの誤用と呼ばれることがありますenv
。元の目的は、(名前が示すように)変更された環境でコマンドを呼び出すことです。また、一部の古いシステム(私の記憶が正しい場合はSunOS 4を含む)はおそらく深刻な問題ではありません env
。このように動作し、多くのスクリプトがこのトリックを使用し、オペレーティングシステムプロバイダがこれを破るために何もしません。それ/usr/bin
env
#!/usr/bin/env
可能非常に古いシステムでスクリプトを実行するのは問題ですが、とにかくスクリプトを変更する必要があるかもしれません。
別の考えられる問題(コメントで指摘したSopalajo de Arrierezに感謝します)は、cronジョブが限られた環境で実行されていることです。特に、一般的$PATH
に/usr/bin:/bin
。正確なパスを指定するか、crontabに行を追加することで設定できます(詳細)。$PATH
/usr/bin/env
$PATH
man 5 crontab
KevinのコメントはPythonvirtualenv
が$PATH
。 (私はvirtualenvを直接使用したことがありません。)#!/usr/bin/env python
python3
答え2
/usr/bin/env がスクリプトを解釈できるため、$PATH
スクリプトの移植性が向上します。
#!/usr/local/bin/python
Pythonが/usr/local/binにインストールされている場合にのみ、スクリプトが実行されます。
#!/usr/bin/env python
$PATH
あなたのとに説明します$PATH
。
したがって、スクリプトはより移植性が高く、Pythonがインストールされているシステム、または追加されたカスタム/usr/bin/python
ディレクトリ/usr/local/bin/python
($PATH
たとえば)から変更することなく実行できます/opt/local/bin/python
。
env
移植性は、ハードコーディングされたパスよりも優れたパスを使用する唯一の理由です。
答え3
目標基準/要件:
使用するかどうかの決定純粋な
または 論理的(/usr/bin/env
) shebangの通訳者パスには2つの主な考慮事項があります。
ㅏ)これ通訳ターゲットシステムで見つけることができます
雨)これ正しいバージョン~の 通訳 ターゲットシステムで見つけることができます
もし私たちが同意するそれ」雨)「うれしい。私たちも同意する:
c) 好ましくは私たちのスクリプト失敗する無効なインタプリタバージョンで実行して、潜在的に一貫性のない結果を得る代わりに。
もし私たちが同意しないそれ」雨)「重要なら、どんな翻訳でも見つかれば十分でしょう。
テスト:
使用により論理的Shebangのインタプリタへのパスは/usr/bin/env
最もスケーラブルなソリューションであり、同じインタプリタへの異なるパスを持つターゲットホストで同じスクリプトを正常に実行できるようにします。人気が高いので、Pythonを使ってテストします。私たちの基準を満たしています。
/usr/bin/env
予測可能で一貫した位置に居住人気のある(いいえ」すべて")オペレーティングシステム? はい:- RHEL 7.5
- Ubuntu18.04
- ラズビアン10(「バスター」)
- OSX 10.15.02
次のPythonスクリプトは仮想エンベロープの内側と外側で実行されます(ピーペンプ使用)テスト中:
#!/usr/bin/env pythonX.x import sys print(sys.version) print('Hello, world!')
スクリプトのshebangは、必要なPythonバージョン番号(すべて同じホストにインストールされている)に応じて変更されます。
#!/usr/bin/env python2
#!/usr/bin/env python2.7
#!/usr/bin/env python3
#!/usr/bin/env python3.5
#!/usr/bin/env python3.6
#!/usr/bin/env python3.7
予想される結果: つまり
print(sys.version)
= です。インストールされている別のPythonバージョンで実行されるたびに、shebangで指定された正しいバージョンが印刷されます。env pythonX.x
./test1.py
テストノート:
- テストはPythonに制限されています。
- PerlはPythonのように
〜しなければならない
/usr/bin
FHS居住 - すべての可能なLinux / Unixyオペレーティングシステムとすべてのオペレーティングシステムバージョンですべての可能な組み合わせをテストするわけではありません。
結論として:
#!/usr/bin/env python
ユーザーのパスで最初に一致するPythonバージョンを使用するのは事実ですが、バージョン番号を指定できます(たとえば、開発者はどのインタプリタが見つかるか気にしません。」#!/usr/bin/env pythonX.x
最初彼らが興味を持っているのは、コードがコードと互換性があることを知っている指定されたインタプリタを使用して実行され、一貫した結果を保証することです。
ファイルシステムのどこでも...
移植性/柔軟性の観点から論理的- /usr/bin/env
- 代わりに純粋な複数のバージョンのテストによると、そのパスはa)、b)、およびc)の要件を満たしているだけでなく、Pythonしかし、異なるオペレーティングシステムの異なるパスにあっても、同じバージョンのインタプリタを探すファジィロジックの利点もあります。
しかし、最大ディストリビューションはFHSを尊重しますが、誰もがそうではありません。。
では、スクリプトはどこにありますか?失敗するバイナリが別の場所にある場合純粋な同じスクリプトを使用してshebangで指定されたパスより論理的道成功 一致するものが見つかるまで続くため、クロスプラットフォームの信頼性とスケーラビリティが向上します。
答え4
特にPerlの場合、これを使用することは#!/usr/bin/env
2つの理由で悪い考えです。
まず、携帯性が悪い。一部のあいまいなプラットフォームでは、envは/usr/binにありません。第二に、もしキス・トンプソンShebang行でパラメータを渡すときに問題が発生する可能性があることに注意してください。最大の移植性のためのソリューションは次のとおりです。
#!/bin/sh
exec perl -x "$0" "$@"
#!perl
これがどのように機能するかについては、「perldoc perlrun」および-xパラメータの説明を参照してください。