Shebang und Pfad

22

Warum braucht ein Shebang einen Weg?

Falsch

#!ruby

Richtig

#!/usr/local/bin/ruby

#!/usr/bin/env ruby

Das Betriebssystem sollte über die Informationen zum Pfad für einen registrierten Befehl verfügen, und warum erwartet es immer noch, dass dieser angegeben wird?

sawa
quelle

Antworten:

22

Wahrscheinlich, um den Kernel einfacher zu halten. Ich glaube nicht, dass der Kernel jemals Ihren Pfad durchsucht, um eine ausführbare Datei zu finden. Das erledigt die C-Bibliothek. #!Die Verarbeitung erfolgt im Kernel, der nicht die Standard-C-Bibliothek verwendet.

Ich glaube auch nicht, dass der Kernel eine Vorstellung davon hat, wie Ihr Weg ist. $PATHist eine Umgebungsvariable und nur Prozesse haben eine Umgebung. Der Kernel tut es nicht. Ich nehme an, es könnte auf die Umgebung des Prozesses zugreifen, der die Ausführung ausgeführt hat, aber ich glaube nicht, dass derzeit im Kernel jemals auf Umgebungsvariablen wie diese zugegriffen wird.

cjm
quelle
5

Sie können PATH-searching-Semantik mit erhalten env, so:

#!/usr/bin/env ruby  

hat die Semantik, die Sie von möchten

#!ruby

Der Grund, PATHder davon abhängt, wird nicht als bewährte Methode angesehen, da das Skript keine Annahmen über den Inhalt der Umgebungsvariablen PATH treffen kann, wodurch das "sequentielle Abhängigkeitsmodell" von Binärdateien verletzt wird, bei denen

  1. /bin Enthält die ausführbaren Dateien, die beim Booten benötigt werden.
  2. /usr/bin Enthält die anderen ausführbaren Dateien, die von der Betriebssysteminstallation verwendet werden.
  3. /usr/local/bin Enthält vom Systemadministrator installierte ausführbare Dateien, die nicht Teil des Basisbetriebssystems sind.
  4. ~/bin Enthält die ausführbaren Dateien des Benutzers.

Jede Ebene sollte später in der Sequenz nicht das Vorhandensein von Binärdateien annehmen, die mehr "Anwendung" sind, sondern sich möglicherweise früher auf Binärdateien stützen, die mehr "Fundament" sind. Und die PATH-Variable tendiert dazu, von anwendungsbezogen zu fundamental zu laufen, was der obigen natürlichen Abhängigkeit entgegengesetzt ist.

Fragen Sie sich, was passiert, wenn ein Skript in ~/binein Skript in /usr/local/binRuby aufruft , um das Problem zu veranschaulichen ? Sollte dieses Skript von der installierten Version des Betriebssystems abhängen /usr/bin/rubyoder von der persönlichen Kopie, über die der Benutzer gerade verfügt ~/bin/ruby? PATHDas Suchen ergibt die unvorhersehbare Semantik, die mit der letzteren verbunden ist (möglicherweise ~/bin/rubyhandelt es sich um eine unterbrochene symbolische Verknüpfung), während das Backen auf dem Weg zu #!der ersteren erfolgt.

Es gibt eigentlich kein anderes plattformunabhängiges "Betriebssystem ... Informationen zum Pfad für einen registrierten Befehl", daher ist es am einfachsten, auf dem Pfad zu bestehen, der in der angegeben wird #!.

Charles Stewart
quelle
0

Ich glaube, so können Sie einen alternativen Dolmetscher angeben, wenn Sie brauchen oder wollen. Beispielsweise:

#!/home/user/myrubyinterpreter

Häufiger mit Shell-Skripten gesehen:

#!/bin/bash
#!/bin/sh
#!/bin/dash
#!/bin/csh
Andrew Lambert
quelle
4
Aber warum sollte das notwendig sein? Sie können Ruby direkt mit ausführen ruby, aber das hindert Sie nicht daran, anzugeben, /home/user/myrubyinterpreterob Sie möchten
Michael Mrozek
Michaels Punkt ist genau das, wonach ich frage.
Sawa
0

Aus dem Classic Shell Scripting- Buch:

Shell-Skripte beginnen normalerweise mit #! /bin/sh. Verwenden Sie den Pfad zu einer POSIX-kompatiblen Shell, wenn Ihre /bin/shnicht POSIX-kompatibel ist. Es gibt auch einige "Fallstricke", auf die Sie achten müssen:

  • Sie müssen den vollständigen Pfadnamen des auszuführenden Interpreters kennen. Dies kann die herstellerübergreifende Portabilität verhindern, da verschiedene Anbieter Dinge an verschiedenen Orten ablegen (z . B. im /bin/awkVergleich zu /usr/bin/awk).
Arturo Herrero
quelle
-2

Es gibt andere Gründe, aber aus Sicherheitssicht möchte ich niemals, dass ein Skript Annahmen über den richtigen Pfad macht. Was ist, wenn es falsch ist und die falsche Shell oder der falsche Interpreter ausgeführt wird? Eine, die von einem böswilligen Benutzer eingefügt wurde? Oder was ist, wenn es auf einer bestimmten Shell basiert und abstürzt, wenn die falsche Shell verwendet wird?

Benutzer können mit ihrem Pfad herumspielen und Sachen brechen - vertraue dem Benutzer nicht :-) Ich habe zahlreiche Angriffe ausgeführt, bei denen der Benutzer das Falsche auf seinem Pfad getan hat - normalerweise Dinge in der falschen Reihenfolge -, damit ich sie unterlaufen kann ein normaler Skriptaufruf.

Ja, ich weiß, wenn Sie das Skript selbst geschrieben haben, können Sie zu Recht behaupten, dass Sie Ihren eigenen Weg gefunden haben, aber ein Dolmetscher kann diese Entscheidungen nicht treffen.

Rory Alsop
quelle
Dieses Problem tritt nur auf, wenn das Skript mit erhöhten Berechtigungen ausgeführt wird. Und das ist ungewöhnlich, weil Shebang und Setxid nicht gut zusammenspielen und es viel mehr zu befürchten gibt als $PATH. . Was LD_PRELOADist , wenn ohne erhöhte Berechtigungen verwendet wird? PS Abgelehnt, weil eine falsche Warnung bezüglich der Sicherheit der Sicherheit abträglich ist.
Gilles 'SO- hör auf böse zu sein'
Ihr Standpunkt zu setxid ist gültig, aber es ist ein perfekt nützlicher Angriffsvektor, also definitiv keine falsche Warnung
Rory Alsop
1
Könnten Sie ein Beispiel für einen Fall nennen, in dem PATHes einen Angriffsvektor gibt und es nicht so viele andere Angriffsvektoren gibt, dass der gesamte Ansatz überdacht werden sollte?
Gilles 'SO- hör auf böse zu sein'
@Gilles - +1 Sie haben auf jeden Fall einen guten Punkt, als ob dies kaputt wäre. Es gibt wahrscheinlich auch andere Möglichkeiten, die genauso gültig sind. In Bezug auf kaputte Dinge, die Sie beheben können, ist dies jedoch einfach.
Rory Alsop