インタプリタへのパスを指定する代わりに、インタプリタの名前があり、シェルが$ PATHを介してそれを見つけられるようにするシェバンを持つことは可能ですか?
そうでない場合、理由はありますか?
インタプリタへのパスを指定する代わりに、インタプリタの名前があり、シェルが$ PATHを介してそれを見つけられるようにするシェバンを持つことは可能ですか?
そうでない場合、理由はありますか?
回答:
PATHルックアップは、一般的な環境変数と同様に、ユーザー空間の標準Cライブラリの機能です。カーネルは、呼び出し元からexecve新しいプロセスに環境を渡す場合を除いて、環境変数を認識しません。
カーネルは、パスexecve(execvpPATHルックアップを実行するなどのラッパー関数に依存)またはシバン(execveコールを内部的に再ルーティングする)のパスに対して解釈を実行しません。そのため、絶対パスをシェバンに入れる必要があります¹。元シェバングの実装では、わずか数行のコードであり、それはかなり以来、拡張されていません。
Unixの最初のバージョンでは、シェルは、スクリプトを呼び出していることに気付いたときに、それ自体を呼び出す作業を行いました。Shebangはいくつかの理由でカーネルに追加されました(Dennis Ritchieによる理論的根拠の要約:
パスレスシェバンでは、環境変数とプロセスにアクセスするためにカーネルを強化するかPATH、PATHルックアップを実行するユーザースペースプログラムをカーネルに実行させる必要があります。最初の方法では、不均衡な量の複雑さをカーネルに追加する必要があります。2番目の方法は、#!/usr/bin/envシバンですでに可能です。
¹ 相対パスを指定すると、プロセスの現在のディレクトリ(スクリプトを含むディレクトリではなく)に対して相対的に解釈されるため、シバンではほとんど役に立ちません。
execveシバン内に相対パスを持つことはほとんど意味がありませんが、カーネルはシバン内またはシバン内に絶対パスを必要としません。
/lib64/ld-linux-x86-64.so.2(ldd出力を参照)。Linuxでは完全に汎用的になっています。binfmtサポート(2.1.43以降)により、インタープリターパス/マジックナンバーまたはファイル拡張子のペアを登録できます。あなたはPE32持つことができる.exeの呼び出しをwineあなたがそれらを実行すると、JavaクラスとJARファイルを呼び出すjavaなどなど、
目に見える以上のことが起こっています。#!行はUnixまたはLinuxカーネルによって解釈されますが、#!シェルの側面ではありません。これはPATH、カーネルが実行する内容を決定する時点では実際には存在しないことを意味します。
どの実行可能ファイルを実行するか、またはperlポータブルな方法などで呼び出すかを知らない場合に対処する最も一般的な方法は、を使用すること#!/usr/bin/env perlです。カーネルが実行され/usr/bin/env、PATH環境変数を継承します。env発見(この例では)perl中PATHと使用execve(2)を実行するためにカーネルを取得するためにシステムコールをperl実行します。
$ strace sleep 1
execve("/usr/bin/sleep", ["sleep", "1"], [/* 99 vars */]) = 0
フルパスへの変換はシェルによって行われます(より一般的にはユーザー空間で)。カーネルは、直接アクセスできるファイル名/パスを期待しています。
システムがPATH変数を調べて実行可能ファイルを検索するようにしたい場合は、shebangをとして書き換えることができます#!/usr/bin/env EXEC。
ただし、この場合も検索を行うのはカーネルではありません。
straceされています(/usr/bin/straceある時点で変換されます)。