GNU/Linux >> Tutoriels Linux >  >> Linux

Pourquoi est-il préférable d'utiliser "#!/usr/bin/env Name" au lieu de "#!/path/to/name" comme Shebang ?

Je remarque que certains scripts que j'ai acquis auprès d'autres ont le shebang #!/path/to/NAME tandis que d'autres (utilisant le même outil, NAME) ont le shebang #!/usr/bin/env NAME .

Les deux semblent fonctionner correctement. Dans les tutoriels (sur Python, par exemple), il semble y avoir une suggestion que ce dernier shebang est meilleur. Mais je ne comprends pas très bien pourquoi il en est ainsi.

Je me rends compte que, pour utiliser ce dernier shebang, NAME doit être dans le PATH alors que le premier shebang n'a pas cette restriction.

De plus, il me semble que le premier serait le meilleur shebang, car il spécifie précisément où se trouve NAME. Ainsi, dans ce cas, s'il existe plusieurs versions de NAME (par exemple, /usr/bin/NAME, /usr/local/bin/NAME), la première casse spécifie laquelle utiliser.

Ma question est pourquoi le premier shebang est-il préféré au second ?

Réponse acceptée :

Critères objectifs/Exigences :

Pour déterminer s'il faut utiliser un absolu ou logique (/usr/bin/env ) chemin d'accès à un interprète dans un she-bang, il y a (2) considérations clés :

a) L'interprète peut être trouvé sur le système cible

b) La version correcte d'interprète peut être trouvé sur le système cible

Si nous ACCEPTONS que "b) ” est souhaitable, nous convenons également que :

c) Il est préférable que nos scripts échouent plutôt que d'exécuter en utilisant une version d'interpréteur incorrecte et d'obtenir potentiellement des résultats incohérents.

Si nous N'ACCEPTONS PAS que "b) ” importe, alors n'importe quel interprète trouvé suffira.

Test :

Depuis l'utilisation d'un logique chemin- /usr/bin/env à l'interpréteur dans le she-bang est la solution la plus extensible permettant au même script de s'exécuter avec succès sur des hôtes cibles avec des chemins différents vers le même interpréteur, nous le testerons - en utilisant Python en raison de sa popularité - pour voir s'il répond nos critères.

  1. Est-ce que /usr/bin/env vivre dans un lieu prévisible et cohérent sur POPULAR (pas "tous ") Systèmes d'exploitation? Oui :
  • RHEL 7.5
  • Ubuntu 18.04
  • Raspbian 10 ("Buster")
  • OSX 10.15.02
  1. Ci-dessous, le script Python exécuté à l'intérieur et à l'extérieur des enveloppes virtuelles (Pipenv utilisé) lors des tests :
    #!/usr/bin/env pythonX.x
    import sys
    print(sys.version)
    print('Hello, world!')
    
  2. Le she-bang dans le script a été basculé par le numéro de version Python souhaité (tous installés sur le même hôte) :
  • #!/usr/bin/env python2
  • #!/usr/bin/env python2.7
  • #!/usr/bin/env python3
  • #!/usr/bin/env python3.5
  • #!/usr/bin/env python3.6
  • #!/usr/bin/env python3.7
  1. Résultats attendus :que print(sys.version) =env pythonX.x . A chaque fois ./test1.py a été exécuté à l'aide d'une version Python installée différente, la version correcte spécifiée dans le she-bang a été imprimée.

  2. Remarques sur les tests :

  • Les tests étaient exclusivement limités à Python
  • Perl :comme Python - DOIT vivre dans /usr/bin selon le FHS
  • Je n'ai pas essayé toutes les combinaisons possibles sur chaque nombre possible de système d'exploitation Linuxy/Unixy et de version de chaque système d'exploitation.
Connexe :Linux – Obtenir les capacités du lecteur de CD/DVD lorsque wodim –devices ne fonctionne pas ?

Conclusion :

Bien qu'il soit VRAI que #!/usr/bin/env python utilisera la première version de Python trouvée dans le chemin de l'utilisateur, nous pouvons modérer ce comportement en spécifiant un numéro de version tel que #!/usr/bin/env pythonX.x . En effet, les développeurs ne se soucient pas de savoir quel interpréteur est trouvé "premier ", tout ce dont ils se soucient, c'est que leur code soit exécuté à l'aide de l'interpréteur spécifié qu'ils savent être compatible avec leur code pour garantir des résultats cohérents - où qu'il se trouve dans le système de fichiers

En termes de portabilité/flexibilité, utiliser une logique /usr/bin/env – plutôt que absolu chemin répond non seulement aux exigences a), b) et c) de mes tests avec différentes versions de Python , mais a également l'avantage de la logique floue pour trouver le même interpréteur de version même s'ils vivent sur des chemins différents sur différents systèmes d'exploitation. Et bien que PLUS les distributions respectent le FHS, pas toutes.

Alors, où un script va ÉCHOUER si le binaire vit dans un absolu différent chemin ensuite spécifié dans shebang, le même script utilisant un logique chemin RÉUSSIT au fur et à mesure qu'il continue jusqu'à ce qu'il trouve une correspondance, offrant ainsi une plus grande fiabilité et une plus grande extensibilité sur toutes les plates-formes.


Linux
  1. Comment Linux gère-t-il plusieurs séparateurs de chemins consécutifs (/home////nom d'utilisateur///fichier) ?

  2. Pourquoi /bin/sh pointe-t-il vers /bin/dash et non /bin/bash ? ?

  3. Quand dois-je utiliser #!/bin/bash et quand #!/bin/sh ?

  4. Pourquoi sur certains systèmes Linux, le système de fichiers racine apparaît-il comme /dev/root au lieu de /dev/<real device node> dans mtab ?

  5. Déplacement du contenu de /bin vers /usr/bin, possible d'annuler ?

Quand dois-je utiliser /dev/shm/ et quand dois-je utiliser /tmp/?

Quelle est la signification de /usr/sbin, /usr/local/sbin et /usr/local/bin ?

Pourquoi mettre des choses autres que /home sur une partition séparée ?

Différence entre /bin et /usr/bin

Pourquoi < ou > sont-ils nécessaires pour utiliser /dev/tcp

Les sites Web doivent-ils vivre dans /var/ ou /usr/ selon l'utilisation recommandée ?