La norme shell POSIX dit sur ce site
http://pubs.opengroup.org/onlinepubs/9699919799/
sur la façon dont les shells utilisent PATH
pour rechercher les exécutables:
"La liste doit être recherchée du début à la fin, en appliquant le nom de fichier à chaque préfixe, jusqu'à ce qu'un fichier exécutable avec le nom spécifié et les autorisations d'exécution appropriées soit trouvé."
Eh bien, ce n'est pas ainsi que cela semble fonctionner dans une implémentation POSIX réelle:
man which
dit:
"renvoie les chemins d'accès des fichiers (ou liens) qui seraient exécutés dans l'environnement actuel, si ses arguments avaient été donnés sous forme de commandes dans un shell strictement conforme à POSIX. Il le fait en recherchant dans le PATH des fichiers exécutables correspondant aux noms des arguments. Il ne suit pas les liens symboliques. "
OK, regardons cette situation:
$ 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, voici un lien symbolique PATH
avec le nom correct, et il est signalé par ls
être exécutable.
which
ne le regarde pas du tout, mais ne s'intéresse qu'à ce qu'il pointe.
Cela malgré le fait que les deux man which
disent explicitement qu'il ne suit pas les liens symboliques (et en effet nous le voyons pas, car which foobar
ne s'imprime pas foobar1
), et aussi que la documentation du shell POSIX citée ci-dessus, ne mentionne jamais de suivre les liens symboliques dans l' PATH
algorithme.
Alors, est which
-ce que les obus existants sont faux, ou est-ce que je ne comprends pas la documentation?
CLARIFIER:
Je connais et peux expliquer le comportement existant. Ma question n'est pas "comment ça marche?". Ce que je sais.
Ma question concerne la documentation: où est mon erreur en suivant la documentation que j'ai citée. Ou la documentation est-elle erronée?
MOTIVATION: Pourquoi je m'en soucie?
Eh bien, je suis un réalisateur. Les différents implémenteurs ont des exigences différentes. Pour moi, l'exigence est que le mot de la norme POSIX actuelle DOIT être suivi EXACTEMENT (ou, plus précisément, le meilleur possible, car la norme elle-même est quelque peu boguée). Comme si c'était la parole de Dieu.
Maintenant, le libellé standard est assez clair - les liens symboliques suivants ne sont pas mentionnés, alors que dans de nombreux autres endroits, il est mentionné où cela doit être fait. Donc, dans ce cas, ne le faites pas.
Cependant, je vérifie toujours comment dash
et je me bash
comporte, juste pour m'assurer. Maintenant, bien sûr, il y a un petit problème ici aussi, dash
même s'il est facturé comme POSIX, il y a beaucoup de petits bogues conformes à POSIX. bash
, Je n'ai pas encore trouvé de bugs avec POSIX, mais ... bash n'est pas réellement POSIX, c'est bien plus que cela.
Alors voilà. Voilà pourquoi je m'en soucie.
la source
$PATH
peut contenir des liens symboliques. Essayezwhich sh
.$PATH
n'a pas de liens symboliques.lstat(2)
), les suivre n'est généralement pas indiqué. Par exemple, la description deopen(2)
ne mentionne que les liens symboliques lorsque l'on parle du comportement deO_CREAT | O_EXCL
. Il n'est pas nécessaire d'indiquer que le fichier cible sera ouvert.Réponses:
Les autorisations du lien symbolique lui-même ne sont pas pertinentes. Vous ne pourriez même pas les changer si vous essayiez.
Ce qui importe, ce sont les autorisations du fichier sous-jacent.
C'est bien d'avoir des répertoires dans votre PATH qui incluent des liens symboliques vers des exécutables. En fait, il est probable que de nombreux exécutables de votre PATH soient des liens symboliques. Par exemple, sur des systèmes de type Debian / Ubuntu:
Documentation
De
man chmod
:Exemple
Le shell a un test,
-x
pour déterminer si un fichier est exécutable. Essayons cela:Ainsi, tout comme vous l'avez trouvé avec
which
, le shell ne considère pas un exécutable de lien logiciel sauf si le fichier sous-jacent est exécutable.Comment ça marche
Sur un système Debian,
which
est un script shell. La section pertinente du code est:Comme vous pouvez le voir, il utilise le
-x
test pour déterminer si un fichier est exécutable.POSIX spécifie le
-x
test comme suit:Ainsi, POSIX vérifie la résolution du nom de chemin . En d'autres termes, il accepte les liens symboliques.
Fonction d'exécution POSIX
La fonction exec POSIX suit les liens symboliques. La spécification POSIX continue longuement pour spécifier les conditions d'erreur qu'elle peut signaler si les liens symboliques sont circulaires ou trop profonds, tels que:
la source
which
est un script shell. Ainsi, il est probable qu'il utilise simplement le-x
test que j'ai montré. Selon POSIX,-x
teste si un fichier "se résout" en un exécutable. Si vous voyez quelque chose de différent, où cherchez-vous?which
fonctionne, ou si c'est-x
ou autre chose. Je suis intéressé de savoir où ne suis-je pas en train de suivre correctement la documentation que j'ai citée.exec
suit les liens symboliques. Cela semble indiquer assez clairement que les fichiers liés par des liens symboliques peuvent être des exécutables sous POSIX.man which
qui dit "Il ne canonise pas les noms de chemin". Cela ne signifie pas qu'il ne suit pas les liens. Cela signifie seulement, comme vous l'avez observé, qu'il ne "canonise" pas les noms.Dans ce cas, les liens symboliques sont suivis de manière transparente, sans canoniser le chemin final. En d'autres termes,
which
peu importe s'il/home/mark/bin
s'agit d'un lien symbolique ou non. Ce qui importe c'est de savoir si le fichier/home/mark/bin/foobar
existe ou non. Il n'a pas besoin d'aplatir manuellement les liens symboliques le long du chemin - le système d'exploitation peut le faire très bien par lui-même.Et en effet, lorsque vous
which
demandez des informations sur le fichier/home/mark/bin/foobar
, le système d'exploitation remarque/home/mark/bin
qu'il s'agit d'un lien symbolique, le suit et le trouve avec succèsfoobar
dans le répertoire cible.Il s'agit du comportement par défaut, sauf si le programme utilise
open(…, O_NOFOLLOW)
oufstatat(…, AT_SYMLINK_NOFOLLOW)
pour accéder au fichier.[commentaires fusionnés]
Alors que vous dites que les utilitaires shell font au cas par cas, ce n'est pas la même chose avec syscalls du noyau: tous les appels liés à fichiers font suivre les liens symboliques par défaut, à moins que le drapeau « nofollow » est donnée. (Même lstat suit les liens symboliques dans tous les composants de chemin sauf le dernier.)
Lorsque la spécification ne mentionne pas explicitement quoi faire avec les liens symboliques, cela implique que le comportement par défaut sera utilisé. C'est-à-dire qu'un shell suivant l'algorithme de chemin ne résout pas les liens symboliques manuellement et ne désactive pas explicitement le système d'exploitation en faisant de même. (Il concatène simplement chaque composant $ PATH avec le nom de l'exécutable.)
Lorsque la page de manuel which (1) indique qu'elle ne suit pas les liens symboliques, cela peut signifier plusieurs choses, mais la version de GNU coreutils l'indique de cette façon:
La portée est beaucoup plus étroite - cela signifie seulement que
which
vous n'essaierez pas de canoniser manuellement tous les chemins pour éliminer les doublons, mais cela n'implique pas que l'outil désactive le lien symbolique suivi par le système d'exploitation en général. Par exemple, si/bin
est un lien symbolique vers/usr/bin
, l'exécutionwhich -a sh
renverra à la fois/bin/sh
et/usr/bin/sh
.la source
which
page de manuel GNU le dit différemment: "Ce qui considérera deux répertoires équivalents comme différents lorsque l'un d'eux contient un chemin avec un lien symbolique."execve("/home/mark/bin/foobar", …)
tous les liens symboliques seront suivis.execve
argument, en fait, dans ma mise en œuvre, c'est laexecl()
même chose. S'il vous plaît, si vous incluez ceci dans votre réponse, j'accepterai.Le shell est conforme à sa documentation en ce qu'il suit les règles de résolution des noms de chemin.
which
est conforme à sa documentation. Les deux font des choses légèrement différentes.La sortie de
which
est le nom et le chemin du fichier du lien, pas le chemin vers lequel pointe le lien symbolique. Ceci est expliqué dans la page de manuel.Lorsqu'une commande est exécutée, le lien est "suivi" conformément à la section 4.13 Résolution de chemin d'accès de la même manière . La clause pertinente pour exécuter un fichier est:
la source