パスレスシバンを使用してみませんか?


24

インタプリタへのパスを指定する代わりに、インタプリタの名前があり、シェルが$ PATHを介してそれを見つけられるようにするシェバンを持つことは可能ですか?

そうでない場合、理由はありますか?


回答:


20

PATHルックアップは、一般的な環境変数と同様に、ユーザー空間の標準Cライブラリの機能です。カーネルは、呼び出し元からexecve新しいプロセスに環境を渡す場合を除いて、環境変数を認識しません。

カーネルは、パスexecveexecvpPATHルックアップを実行するなどのラッパー関数に依存)またはシバン(execveコールを内部的に再ルーティングする)のパスに対して解釈を実行しません。そのため、絶対パスをシェバンに入れる必要があります¹。元シェバングの実装では、わずか数行のコードであり、それはかなり以来、拡張されていません。

Unixの最初のバージョンでは、シェルは、スクリプトを呼び出していることに気付いたときに、それ自体を呼び出す作業を行いました。Shebangはいくつかの理由でカーネルに追加されました(Dennis Ritchieによる理論的根拠の要約:

  • 呼び出し元は、実行するプログラムがシェルスクリプトかネイティブバイナリかを心配する必要はありません。
  • スクリプト自体は、呼び出し元の代わりに使用するインタープリターを指定します。
  • カーネルはログ内のスクリプト名を使用します。

パスレスシェバンでは、環境変数とプロセスにアクセスするためにカーネルを強化するかPATH、PATHルックアップを実行するユーザースペースプログラムをカーネルに実行させる必要があります。最初の方法では、不均衡な量の複雑さをカーネルに追加する必要があります。2番目の方法は、#!/usr/bin/envシバンですでに可能です。

¹ 相対パスを指定すると、プロセスの現在のディレクトリ(スクリプトを含むディレクトリではなく)に対して相対的に解釈されるため、シバンではほとんど役に立ちません。


2
いいえ、execveシバン内に相対パスを持つことはほとんど意味がありませんが、カーネルはシバン内またはシバン内に絶対パスを必要としません。
ステファンシャゼル

3
「shebangが内部的にexecve呼び出しをどのように再ルーティングするか」に興味がある人のために:それは実際には、それらを必要とする実行可能ファイルでインタープリターを実行するための汎用メカニズムの一部です。動的にリンクされたELF実行可能ファイルは、「解釈」されます/lib64/ld-linux-x86-64.so.2ldd出力を参照)。Linuxでは完全に汎用的になっています。binfmtサポート(2.1.43以降)により、インタープリターパス/マジックナンバーまたはファイル拡張子のペアを登録できます。あなたはPE32持つことができる.exeの呼び出しをwineあなたがそれらを実行すると、JavaクラスとJARファイルを呼び出すjavaなどなど、
ピーター・コルド

#!/ usr / bin / env -S [shebang]は、パスを知らずにノードを実行するために必要でした(nvmを使用して-当初予想した場所とは異なる場所に配置します)。
TamusJRoyce

-Sはcoreutils 8.30以降でのみ使用可能です。gitlab.com/gnuwget/wget/commit/…を参照してください。
ティムリューセンrockdaboot

19

目に見える以上のことが起こっています。#!行はUnixまたはLinuxカーネルによって解釈されますが、#!シェルの側面ではありません。これはPATH、カーネルが実行する内容を決定する時点では実際には存在しないことを意味します。

どの実行可能ファイルを実行するか、またはperlポータブルな方法などで呼び出すかを知らない場合に対処する最も一般的な方法は、を使用すること#!/usr/bin/env perlです。カーネルが実行され/usr/bin/envPATH環境変数を継承します。env発見(この例では)perlPATHと使用execve(2)を実行するためにカーネルを取得するためにシステムコールをperl実行します。


4
$ strace sleep 1
execve("/usr/bin/sleep", ["sleep", "1"], [/* 99 vars */]) = 0

フルパスへの変換はシェルによって行われます(より一般的にはユーザー空間で)。カーネルは、直接アクセスできるファイル名/パスを期待しています。

システムがPATH変数を調べて実行可能ファイルを検索するようにしたい場合は、shebangをとして書き換えることができます#!/usr/bin/env EXEC

ただし、この場合も検索を行うのはカーネルではありません。


1
フルパスへの変換はシェル Thanks によって行われますが、例はそれを説明することになっていますか?ご覧のとおり、シェルは2つの引数で実行straceされています(/usr/bin/straceある時点で変換されます)。
アロイスマーダル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.