Ist es möglich, dass ein Shebang den Namen des Interpreters enthält und die Shell ihn über $ PATH findet, anstatt einen Pfad zu einem Interpreter anzugeben?
Wenn nicht, gibt es einen Grund dafür?
Ist es möglich, dass ein Shebang den Namen des Interpreters enthält und die Shell ihn über $ PATH findet, anstatt einen Pfad zu einem Interpreter anzugeben?
Wenn nicht, gibt es einen Grund dafür?
Antworten:
PATH-Lookup ist eine Funktion der Standard-C-Bibliothek im Benutzerbereich, ebenso wie Umgebungsvariablen im Allgemeinen. Der Kernel sieht keine Umgebungsvariablen, es sei denn, er übergibt eine Umgebung vom Aufrufer execvean den neuen Prozess.
Der Kernel führt keine Interpretation des Pfades in execve(es liegt an den Wrapper-Funktionen, wie zum Beispiel execvpder PATH-Suche) oder in einem Shebang (der den execveAnruf mehr oder weniger intern umleitet) durch. Sie müssen also den absoluten Pfad in den shebang¹ setzen. Die ursprüngliche shebang-Implementierung bestand nur aus wenigen Codezeilen und wurde seitdem nicht wesentlich erweitert.
In den ersten Versionen von Unix hat die Shell sich selbst aufgerufen, als sie bemerkte, dass Sie ein Skript aufgerufen haben. Shebang wurde aus mehreren Gründen in den Kernel aufgenommen (Zusammenfassung der Begründung von Dennis Ritchie :
Pathless Shebangs müssten entweder den Kernel erweitern, um auf Umgebungsvariablen und -prozesse zuzugreifen PATH, oder den Kernel ein Userspace-Programm ausführen lassen, das die PATH-Suche durchführt. Die erste Methode erfordert das Hinzufügen einer unverhältnismäßigen Menge an Komplexität zum Kernel. Die zweite Methode ist bereits mit einem #!/usr/bin/envShebang möglich .
¹ Wenn Sie einen relativen Pfad angeben, wird dieser relativ zum aktuellen Verzeichnis des Prozesses interpretiert (nicht zum Verzeichnis, in dem sich das Skript befindet), was in einem Shebang kaum sinnvoll ist.
execvenoch im Shebang, obwohl es wenig sinnvoll ist, einen relativen Pfad in einem Shebang zu haben.
/lib64/ld-linux-x86-64.so.2(siehe lddAusgabe). Linux macht es vollständig generisch: Mit der binfmtUnterstützung (seit 2.1.43) können Sie Interpreter-Pfad / Magic-Number-or-File-Extension-Paare registrieren. Sie können PE32s .exeaufrufen, winewenn Sie sie ausführen, Java-Klassen- und JAR-Dateien aufrufen javausw. usw.
Es ist mehr los als man denkt. #!Zeilen werden vom Unix- oder Linux-Kernel interpretiert, #!sind aber kein Aspekt von Shells. Dies bedeutet, dass PATHes zu dem Zeitpunkt, an dem der Kernel entscheidet, was ausgeführt werden soll , nicht wirklich existiert.
Die gebräuchlichste Möglichkeit, nicht zu wissen, welche ausführbare Datei ausgeführt werden soll, oder auf perltragbare Weise oder auf ähnliche Weise aufzurufen , ist die Verwendung von #!/usr/bin/env perl. Der Kernel wird ausgeführt /usr/bin/env, der eine PATHUmgebungsvariable erbt . envfindet (in diesem Beispiel) perlin PATHund verwendet den execve(2)Systemaufruf, um den Kernel zum Ausführen der perlausführbaren Datei zu veranlassen.
$ strace sleep 1
execve("/usr/bin/sleep", ["sleep", "1"], [/* 99 vars */]) = 0
Die Konvertierung in den vollständigen Pfad erfolgt über die Shell (allgemeiner: im Userspace). Der Kernel erwartet einen Dateinamen / Pfad, auf den er direkt zugreifen kann.
Wenn Sie möchten, dass das System Ihre ausführbare Datei durch Durchsuchen der PATH-Variablen findet, können Sie Ihren shebang als umschreiben #!/usr/bin/env EXEC.
Aber auch in diesem Fall ist es nicht der Kernel, der die Suche durchführt.
strace( /usr/bin/straceirgendwann konvertiert ) mit 2 Argumenten.