パスなしのshebangを使用しないのはなぜですか?

パスなしのshebangを使用しないのはなぜですか?

インタプリタのパスを指定せずに、代わりにインタプリタの名前を持ち、シェルが$ PATHを介して検索できるようにするshebangを持つことはできますか?

そうでない場合、何らかの理由がありますか?

答え1

PATHルックアップは、環境変数と同様に、ユーザー空間の標準Cライブラリの機能です。カーネルは、呼び出し側から環境変数を渡さない限り、環境変数を見ることはできません。execve新しいプロセスとして。

execveカーネルは(PATHルックアップの実行などのラッパー関数によって異なりますexecvp)またはshebang(ほぼexecve内部的に呼び出しを再ルーティングする)でパス解析を実行しません。したがって、shebangに絶対パスを配置する必要があります。これもともとShebanの実装ほんの数行のコードが必要で、それ以降は大幅に拡張されていません。

Unixの最初のバージョンでは、シェルはユーザーがスクリプトを呼び出していることに気づいたときに独自の呼び出し操作を実行しました。 Shebangはいくつかの理由でカーネルに追加されました(要約するとデニスリッチの基本:

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

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

1相対パスを入力すると(スクリプトを含むディレクトリではなく)、プロセスの現在のディレクトリに基づいて解釈されるため、shebangではほとんど使用されません。

答え2

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

移植可能な方法、または同様の方法で実行または呼び出す実行可能ファイルを知らない場合を処理する最も一般的な方法は、環境変数を継承する.kernel実行をperl使用することです。この例では、システムコールを見つけてカーネルに実行可能ファイルを実行するように指示します。#!/usr/bin/env perl/usr/bin/envPATHenvperlPATHexecve(2)perl

答え3

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

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

システムにPATH変数を表示して実行可能ファイルを見つけるようにするには、shebangを#!/usr/bin/env EXEC

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

関連情報