Le secret de la première ligne des scripts Linux : Que signifient #!/usr/bin/env bash et #!/bin/bash ?

Lorsque vous rédigez un script sous Linux, il est courant d'ajouter cette ligne en haut :

#!/usr/bin/env bash

ou encore

#!/bin/bash

À première vue, cela ressemble à un simple commentaire... Mais quelle est la véritable nature de cette ligne ? Et surtout, quelles sont les différences entre ces deux formes ? Dans cet article, nous allons décortiquer cette ligne mystérieuse pour comprendre son rôle et savoir quand utiliser l'une ou l'autre.


1. Ce n'est pas un commentaire : Qu'est-ce que le shebang ?

Cette ligne, commençant par #!, est appelée shebang.

#!/bin/bash

Du point de vue du shell, puisque cela commence par #, cela ressemble clairement à un « commentaire ». Cependant, pour le système d'exploitation (le noyau), il ne s'agit pas d'un commentaire, mais d'une directive qui indique :

« Où trouver le programme interpréteur pour exécuter ce script. »

Autrement dit :

  • #!/bin/bash → « Exécute ce fichier avec /bin/bash. »
  • #!/usr/bin/env bash → « Trouve l'interpréteur bash via env et exécute ce fichier avec celui-ci. »

2. Comment le noyau exécute-t-il un script ?

En simplifiant le processus d'exécution, cela se déroule comme suit :

  1. L'utilisateur exécute un script avec les droits d'exécution.
chmod +x script.sh
./script.sh
  1. Le noyau lit script.sh.
  2. Il vérifie si les deux premiers caractères du fichier sont #!.
  3. Si c'est le cas, il interprète le reste de la ligne comme :
  • « Le chemin de l'interpréteur + ses arguments »
  • Et exécute ce programme en lui passant le chemin du fichier script comme argument.

Par exemple, si la première ligne de script.sh est :

#!/bin/bash

Le noyau effectue en réalité une action que l'on peut conceptualiser ainsi :

/bin/bash script.sh

Autrement dit, le noyau exécute une action similaire à celle que nous ferions en tapant directement bash script.sh.

Note : Il ne doit pas y avoir d'espace avant #!/. Le premier caractère du fichier doit être #, et le second !.


3. Signification et caractéristiques de #!/bin/bash

C'est la forme la plus couramment rencontrée.

#!/bin/bash

Signification

  • « Ce script est un script bash, et bash se trouve dans /bin/bash. »
  • Le noyau exécutera toujours /bin/bash pour ce script.

Avantages

  • Clarté : L'utilisation systématique de /bin/bash rend prévisible la version de bash qui sera employée.
  • Performance/Simplicité : Le script est exécuté directement, sans passer par env, ce qui élimine le processus de recherche du chemin.
  • Sur de nombreuses distributions Linux, /bin/bash est considéré comme un « emplacement standard » de facto.

Inconvénients

  • Manque de portabilité

  • Sur certains systèmes, bash peut se trouver à un autre emplacement, comme /usr/bin/bash ou /usr/local/bin/bash.

  • Certains systèmes peuvent ne pas avoir bash du tout, et ne disposer que de /bin/sh.
  • Les chemins peuvent différer, notamment sur macOS, les systèmes basés sur BSD, NixOS et certains environnements de conteneurs.

4. Signification et caractéristiques de #!/usr/bin/env bash

C'est la forme la plus couramment rencontrée dans les scripts modernes.

#!/usr/bin/env bash

L'élément clé ici est /usr/bin/env.

  • env est un utilitaire qui aide à « définir/vérifier les variables d'environnement + rechercher des programmes dans le PATH ».

  • On peut considérer que le noyau exécute réellement ceci :

bash /usr/bin/env bash script.sh

  • env examine la variable d'environnement PATH du système pour trouver et exécuter l'exécutable bash.

Avantages

  1. Portabilité (fonctionne bien dans divers environnements)
  • Que bash se trouve dans /bin/bash, /usr/bin/bash, ou /usr/local/bin/bash,
  • env le trouvera tant qu'il est correctement enregistré dans le PATH.
  1. Utilisation de la version de bash adaptée à l'environnement utilisateur
  • Si l'utilisateur a personnalisé son PATH pour utiliser une version spécifique de bash en priorité, c'est cette version qui sera utilisée.
  1. Utilisation du même modèle pour Python et d'autres langages

python #!/usr/bin/env python3

Inconvénients

  1. Nécessite la présence de /usr/bin/env
  • Bien qu'il soit présent sur presque tous les systèmes Unix/Linux modernes, il pourrait manquer dans des environnements très spécifiques.
  1. Un interpréteur différent peut être sélectionné en fonction du PATH
  • Si la configuration du PATH est corrompue ou si une version inattendue de bash est trouvée en premier, une version non désirée pourrait être exécutée.
  1. Nécessite une attention particulière en matière de sécurité
  • Dans des environnements très sensibles à la sécurité, la préférence peut aller aux chemins absolus plutôt qu'à la recherche d'interpréteurs basée sur le PATH.

5. Comparaison des deux approches

Voici un tableau comparatif simplifié.

Critère #!/bin/bash #!/usr/bin/env bash
Méthode de spécification de l'interpréteur Chemin absolu fixe Recherche via PATH
Portabilité (compatibilité multi-systèmes) Faible (casse si le chemin diffère) Élevée (OK si bash est dans le PATH)
Quelle version de bash est utilisée Toujours /bin/bash Le premier bash trouvé dans le PATH
Garantie de la version souhaitée Relativement facile Peut varier selon l'état du PATH
Sécurité/Contrôle Plus fort (chemin fixe) Légèrement plus souple (dépend du PATH)
Tendance générale actuelle Style relativement ancien Plus souvent recommandé de nos jours

6. Quand utiliser quelle approche ?

Pour répondre à la question « En fin de compte, que dois-je utiliser ? », voici une ventilation par situation.

1) Scripts personnels / de développement d'équipe (environnements de développement courants)

  • Généralement, la recommandation est la suivante :

bash #!/usr/bin/env bash

  • Raisons :

  • L'emplacement de bash peut varier sur les serveurs gérés par les développeurs, les environnements locaux, les environnements CI, etc.

  • La recherche et l'exécution basées sur le PATH sont plus flexibles, et les outils/scripts modernes préfèrent cette approche.

2) Scripts d'exploitation adaptés à un environnement serveur spécifique

  • Par exemple, si tous les serveurs de l'entreprise ont bash installé en commun dans /bin/bash,

  • Et si l'environnement serveur est relativement fixe :

bash #!/bin/bash

  • Raisons :

  • Assure l'utilisation du même interpréteur en permanence.

  • Réduit les comportements inattendus dus aux modifications du PATH.

3) Si vous souhaitez une portabilité maximale ?

  • Si vous envisagez un environnement où « bash pourrait ne pas être installé du tout », il faut d'abord se demander si un script dépendant de bash est la bonne approche.

  • Si possible, écrivez en sh :

bash #!/bin/sh

  • Cette approche fonctionnera dans un éventail beaucoup plus large d'environnements. Cependant, il ne faut pas utiliser la syntaxe propre à bash ([[ ]], tableaux, traitement étendu des chaînes de caractères, etc.).

7. Conseils pratiques pour l'utilisation de #!/usr/bin/env bash

1) Méthode d'exécution du script

Pour utiliser correctement le shebang, il est préférable de ne pas faire ceci :

bash script.sh   # ← L'exécution de cette manière rend le shebang presque inutile

Mais plutôt de l'utiliser comme suit :

chmod +x script.sh   # Accorder les droits d'exécution
./script.sh          # Exécuter directement

C'est ainsi que le noyau lira le #! et utilisera l'interpréteur spécifié.

2) Vérification du passage des arguments

Prenons l'exemple de test.sh créé comme suit :

#!/usr/bin/env bash

echo "Interpréteur: $0"
echo "Arguments: $@"

Exécution :

chmod +x test.sh
./test.sh hello world

Sortie :

Interpréteur: ./test.sh
Arguments: hello world

Ici, $0 représente le « chemin du fichier script lui-même », et il suffit de se rappeler que le noyau l'exécute en réalité comme /usr/bin/env bash test.sh hello world.


8. Foire aux questions

J'ai déjà vu des scripts écrits sans shebang. Est-ce normal ?

  • C'est exact, le shebang n'est pas toujours nécessaire.

  • Si vous exécutez le script en spécifiant directement l'interpréteur, comme ci-dessous, le shebang n'est pas nécessaire. Même s'il est présent, il sera ignoré.

bash bash myscript.sh python3 myscript.py

  • Cependant, si vous souhaitez l'exécuter comme suit, il est absolument indispensable :

bash ./myscript.sh ./myscript.py

  • En particulier, pour les scripts destinés à être utilisés comme des « outils » par d'autres, le shebang est pratiquement obligatoire.

« J'ai vu #!/bin/env fonctionner aussi, pas seulement #!/usr/bin/env ? »

  • Sur certains systèmes, /bin/env peut exister.
  • Cependant, /usr/bin/env est généralement l'emplacement standard le plus universel.
  • À moins d'une raison spécifique, il est plus sûr d'utiliser #!/usr/bin/env ….

9. Résumé

  • #!/usr/bin/env bash ou #!/bin/bash ne sont pas des commentaires, mais des directives qui indiquent au noyau avec quel interpréteur exécuter le script.
  • #!/bin/bash

  • Utilise toujours /bin/bashPrévisible dans un environnement fixe, mais potentiellement moins portable.

  • #!/usr/bin/env bash

  • Cherche bash dans le PATHPlus flexible et portable, mais dépend de l'état du PATH.

  • Pour la rédaction de scripts « modernes » dans des environnements de développement/déploiement courants, il est recommandé d'utiliser #!/usr/bin/env bash par défaut.
image du shebang dans un script Linux
Image du principe de fonctionnement du shebang