Der POSIX-Shell-Standard besagt dies auf dieser Site
http://pubs.opengroup.org/onlinepubs/9699919799/
Informationen darüber, wie Shells PATH
zur Suche nach ausführbaren Dateien verwendet werden:
"Die Liste wird von Anfang bis Ende durchsucht, wobei der Dateiname auf jedes Präfix angewendet wird, bis eine ausführbare Datei mit dem angegebenen Namen und den entsprechenden Ausführungsberechtigungen gefunden wird."
Nun, so scheint es in einer echten POSIX-Implementierung nicht zu funktionieren:
man which
sagt:
msgstr "" "gibt die Pfadnamen der Dateien (oder Links) zurück, die in der aktuellen Umgebung ausgeführt würden, wenn ihre Argumente als Befehle in einer streng POSIX - konformen Shell angegeben worden wären. Dies geschieht, indem der Pfad nach ausführbaren Dateien durchsucht wird, die mit den Namen der Dateien übereinstimmen Argumente. Es folgt keinen symbolischen Verknüpfungen. "
OK, schauen wir uns diese Situation an:
$ pwd
/home/mark
$ echo $PATH
/home/mark/bin:
...
$ ls -l bin/foobar
lrwxrwxrwx 1 mark mark 18 Dec 12 22:51 bin/foobar -> /home/mark/foobar1
$ touch foobar1
$ which foobar
$ chmod a+x foobar1
$ which foobar
/home/mark/bin/foobar
OK, hier ist ein symbolischer Link PATH
mit dem richtigen Namen, und es wird gemeldet ls
, dass er ausführbar ist.
which
schaut es gar nicht an, sondern interessiert sich nur dafür, worauf es hinweist.
Trotz der Tatsache, dass beide man which
ausdrücklich besagen, dass sie keinen symbolischen Links folgen (und wir sehen, dass sie nicht folgen, weil which foobar
sie nicht gedruckt werden foobar1
) und dass in der oben zitierten POSIX-Shell-Dokumentation niemals erwähnt wird, dass Symlinks im PATH
Algorithmus folgen .
Ist which
und sind die vorhandenen Shells falsch oder verstehe ich die Dokumentation nicht?
ZU KLÄREN:
Ich kenne und kann das vorhandene Verhalten erklären. Meine Frage ist nicht "Wie funktioniert das?". Dass ich weiß.
Meine Frage bezieht sich auf die Dokumentation: Wo liegt mein Fehler bei der Befolgung der von mir zitierten Dokumentation? Oder ist die Dokumentation falsch?
MOTIVATION: Warum kümmert es mich?
Nun, ich bin ein Implementierer. Unterschiedliche Implementierer haben unterschiedliche Anforderungen. Für mich ist die Anforderung, dass das Wort des aktuellen POSIX-Standards GENAU befolgt werden MUSS (oder genauer gesagt, das Beste, weil der Standard selbst etwas fehlerhaft ist). Als ob es das Wort Gottes wäre.
Nun ist der Standardtext ziemlich klar - folgende Symlinks werden nicht erwähnt, an vielen anderen Stellen wird erwähnt, wo dies getan werden muss. Also in diesem Fall nicht.
Ich überprüfe jedoch immer genau, wie dash
und wie ich mich bash
verhalte, um sicherzugehen. Jetzt gibt es natürlich auch hier ein kleines Problem, dash
obwohl es als POSIX berechnet wird und viele kleine Fehler in Übereinstimmung mit POSIX aufweist. bash
Ich habe noch keine Bugs mit POSIX gefunden, aber ... bash ist nicht wirklich POSIX, es ist viel mehr.
Da haben Sie es also. Deshalb ist es mir wichtig.
quelle
$PATH
Dose enthält Symlinks. Versuchen Sie eswhich sh
.$PATH
hat keine Symlinks.lstat(2)
). Beispielsweise werden in der Beschreibungopen(2)
nur Symlinks erwähnt, wenn über das Verhalten von gesprochen wirdO_CREAT | O_EXCL
. Es muss nicht angegeben werden, dass die Zieldatei geöffnet wird.Antworten:
Die Berechtigungen des Symlinks selbst sind irrelevant. Sie könnten sie nicht einmal ändern, wenn Sie es versuchen würden.
Entscheidend sind die Berechtigungen der zugrunde liegenden Datei.
Es ist in Ordnung, dass Verzeichnisse in Ihrem PATH Symlinks zu ausführbaren Dateien enthalten. In der Tat ist es wahrscheinlich, dass viele ausführbare Dateien in Ihrem PATH Symlinks sind. Zum Beispiel auf Debian / Ubuntu-ähnlichen Systemen:
Dokumentation
Von
man chmod
:Beispiel
Die Shell hat einen Test,
-x
um festzustellen, ob eine Datei ausführbar ist. Lass es uns versuchen:So betrachtet
which
die Shell , wie Sie es bei festgestellt haben , eine ausführbare Softlink-Datei nur dann als ausführbar, wenn die zugrunde liegende Datei ausführbar ist.Wie was funktioniert
Auf einem Debian-System
which
ist ein Shell-Skript. Der relevante Abschnitt des Codes lautet:Wie Sie sehen, wird der
-x
Test verwendet, um festzustellen, ob eine Datei ausführbar ist.POSIX spezifiziert den
-x
Test wie folgt:So prüft POSIX , was der Pfad löst zu. Mit anderen Worten, es akzeptiert Symlinks.
POSIX-Exec-Funktion
Die POSIX-Exec-Funktion folgt symbolischen Links. Die POSIX-Spezifikation wird ausführlich beschrieben, um Fehlerzustände anzugeben, die möglicherweise gemeldet werden, wenn Symlinks zirkulär oder zu tief sind, z.
quelle
which
handelt es sich um ein Shell-Skript. Daher ist es wahrscheinlich nur mit dem-x
Test, den ich gezeigt habe. Prüft laut POSIX,-x
ob eine Datei in eine ausführbare Datei "aufgelöst" wird. Wenn Sie etwas anderes sehen, wo suchen Sie dann?which
funktioniert oder ob es-x
etwas anderes ist. Ich bin interessiert zu wissen, wo ich die von mir zitierte Dokumentation nicht richtig verfolge.exec
Funktion folgt symbolischen Links . Das scheint ziemlich deutlich zu machen, dass symbolisch verknüpfte Dateien unter POSIX ausführbar sein können.man which
überprüft, in dem steht : "Pfadnamen werden nicht kanonisiert." Das heißt nicht, dass es den Links nicht folgt. Das bedeutet nur, wie Sie bemerkt haben, dass es die Namen nicht "kanonisiert".In diesem Fall werden Symlinks transparent verfolgt, ohne den endgültigen Pfad zu kanonisieren. Mit anderen Worten,
which
es ist egal, ob/home/mark/bin
es sich um einen Symlink handelt oder nicht. Was es interessiert, ist, ob die Datei/home/mark/bin/foobar
existiert oder nicht. Es ist nicht erforderlich , Symlinks entlang des Pfads manuell zu reduzieren - das Betriebssystem kann dies problemlos alleine tun.Und tatsächlich, wenn
which
nach Dateiinformationen gefragt wird/home/mark/bin/foobar
, stellt das Betriebssystem fest,/home/mark/bin
dass es sich um einen Symlink handelt, folgt diesem und findet ihn erfolgreichfoobar
im Zielverzeichnis.Dies ist das Standardverhalten, es sei denn, das Programm verwendet
open(…, O_NOFOLLOW)
oder,fstatat(…, AT_SYMLINK_NOFOLLOW)
um auf die Datei zuzugreifen.[Kommentare zusammengeführt in]
Während man sagt , dass Shell - Utilities es tut auf einer Fall-zu-Fall - Basis, ist es nicht das gleiche mit Kernel syscalls: alle dateibezogenen Anrufe tun standardmäßig Symlinks folgen, es sei denn , das „nofollow“ Flag gegeben wird. (Sogar lstat folgt symbolischen Verknüpfungen in allen Pfadkomponenten mit Ausnahme der letzten.)
Wenn in der Spezifikation nicht explizit angegeben ist, was mit Symlinks geschehen soll, wird das Standardverhalten verwendet. Das heißt, eine Shell, die dem Pfadalgorithmus folgt, löst Symlinks weder manuell auf, noch deaktiviert sie explizit das Betriebssystem, indem sie dasselbe tut. (Es verkettet einfach jede $ PATH-Komponente mit dem Namen der ausführbaren Datei.)
Wenn die what (1) -Handbuchseite besagt, dass sie keinen Symlinks folgt, kann das verschiedene Dinge bedeuten, aber die GNU-Coreutils-Version sagt es so aus:
Das ist viel enger gefasst - es bedeutet nur,
which
dass nicht versucht wird, alle Pfade zum Entfernen von Duplikaten manuell zu kanonisieren, aber dies bedeutet nicht, dass das Tool das Verfolgen von Symlinks durch das Betriebssystem im Allgemeinen ablehnt. Zum Beispiel, wenn/bin
ein Link zu/usr/bin
, läuftwhich -a sh
kehrt beide/bin/sh
und/usr/bin/sh
.quelle
which
Handbuchseite heißt es anders: "Zwei gleichwertige Verzeichnisse werden als unterschiedlich betrachtet, wenn eines einen Pfad mit einem symbolischen Link enthält."execve("/home/mark/bin/foobar", …)
, werden alle Symlinks befolgt.execve
Argument, tatsächlich ist es in meiner Implementierungexecl()
dasselbe. Bitte, wenn Sie dies in Ihre Antwort aufnehmen, werde ich akzeptieren.Die Shell entspricht der Dokumentation, indem sie die Regeln für die Auflösung von Pfadnamen befolgt.
which
entspricht seiner Dokumentation. Die beiden machen etwas unterschiedliche Dinge.Die Ausgabe von
which
ist der Dateiname und der Pfad des Links, nicht der Pfad, auf den der Symlink verweist. Dies ist in der Manpage angegeben.Wenn ein Befehl ausgeführt wird, wird der Verknüpfung gemäß Abschnitt 4.13 Pfadnamenauflösung in derselben "gefolgt" . Die relevante Klausel zum Ausführen einer Datei lautet:
quelle