Pourquoi tous les fichiers de script commencent-ils par
#!/bin/sh
ou avec
#!/bin/csh
Est-ce nécessaire? Quel est le but de cela? Et quelle est la différence entre les deux?
Pourquoi tous les fichiers de script commencent-ils par
#!/bin/sh
ou avec
#!/bin/csh
Est-ce nécessaire? Quel est le but de cela? Et quelle est la différence entre les deux?
Réponses:
Ceci est connu comme un Shebang
:
http://en.wikipedia.org/wiki/Shebang_(Unix)
#! interpréteur [arg-facultatif]
Un shebang n'est pertinent que lorsqu'un script a l'autorisation d'exécution (par exemple chmod u + x script.sh).
Lorsqu'un shell exécute le script, il utilise l'interpréteur spécifié.
Exemple:
#!/bin/bash
# file: foo.sh
echo 1
$ chmod u+x foo.sh
$ ./foo.sh
1
La #!
ligne indique au noyau (spécifiquement, l'implémentation de l' execve
appel système) que ce programme est écrit dans un langage interprété; le chemin absolu qui suit identifie l'interpréteur. Les programmes compilés en code machine commencent par une séquence d'octets différente - sur la plupart des Unix modernes, 7f 45 4c 46
( ^?ELF) qui les identifie comme tels.
Vous pouvez placer un chemin absolu vers n'importe quel programme de votre choix après le #!
, tant que ce programme n'est pas lui-même un #!
script. Le noyau réécrit une invocation de
./script arg1 arg2 arg3 ...
où ./script
commence par, disons, #! /usr/bin/perl
comme si la ligne de commande avait effectivement été
/usr/bin/perl ./script arg1 arg2 arg3
Ou, comme vous l'avez vu, vous pouvez utiliser #! /bin/sh
pour écrire un script destiné à être interprété par sh
.
La #!
ligne n'est traitée que si vous appelez directement le script ( ./script
sur la ligne de commande); le fichier doit également être exécutable ( chmod +x script
). Si vous faites, sh ./script
la #!
ligne n'est pas nécessaire (et sera ignorée si elle est présente), et le fichier n'a pas besoin d'être exécutable. Le but de cette fonctionnalité est de vous permettre d'appeler directement des programmes en langage interprété sans avoir à savoir dans quelle langue ils sont écrits. (Faites grep '^#!' /usr/bin/*
- vous découvrirez qu'un grand nombre de programmes de base utilisent en fait cette fonctionnalité.)
Voici quelques règles d'utilisation de cette fonctionnalité:
#!
doit être les deux premiers octets du fichier. En particulier, le fichier doit être dans un encodage compatible ASCII (par exemple, UTF-8 fonctionnera, mais UTF-16 ne le fera pas) et ne doit pas commencer par une "marque d'ordre d'octet" , sinon le noyau ne le reconnaîtra pas comme un #!
scénario.#!
doit être un chemin absolu (commence par /
). Il ne peut pas contenir de caractères d'espace, de tabulation ou de nouvelle ligne.#!
et le /
. N'y mettez pas plus d'un espace.#!
ligne, elles ne seront pas développées.#! /usr/bin/awk -f
), parfois c'est juste utile ( #! /usr/bin/perl -Tw
). Malheureusement, vous ne pouvez pas mettre deux arguments ou plus après le chemin absolu.#! /usr/bin/env interpreter
place de #! /absolute/path/to/interpreter
. C'est presque toujours une erreur. Cela rend le comportement de votre programme dépendant de la $PATH
variable de l'utilisateur qui appelle le script. Et tous les systèmes ne l'ont pas fait env
en premier lieu.setuid
ou les setgid
privilèges ne peuvent pas utiliser #!
; ils doivent être compilés en code machine. (Si vous ne savez pas ce que setuid
c'est, ne vous inquiétez pas.)En ce qui concerne csh
, cela se rapporte à sh
peu près à ce que le substitut de thé avancé Nutrimat fait au thé. Il a (ou plutôt eu; les implémentations modernes sh
ont rattrapé) un certain nombre d'avantages par rapport sh
à une utilisation interactive, mais l'utiliser (ou son descendant tcsh
) pour le script est presque toujours une erreur . Si vous êtes nouveau dans le script shell en général, je vous recommande fortement de l'ignorer et de vous concentrer sur sh
. Si vous utilisez un csh
parent comme shell de connexion, basculez vers bash
ou zsh
, afin que le langage de commande interactif soit le même que le langage de script que vous apprenez.
#!
; aucun commentaire pour savoir si c'est du bon style. Voir cette question et ma réponse pour une discussion sur les avantages et les inconvénients du #!/usr/bin/env
hack.
#!/usr/bin/env
était la bonne chose, mais je reste d'avis que c'est presque toujours une mauvaise idée.
Ceci définit le shell (interpréteur de commandes) que vous utilisez pour interpréter / exécuter votre script. Chaque shell est légèrement différent dans la façon dont il interagit avec l'utilisateur et exécute des scripts (programmes).
Lorsque vous tapez une commande à l'invite Unix, vous interagissez avec le shell.
Par exemple, #!/bin/csh
fait référence au C-shell, /bin/tcsh
au t-shell, /bin/bash
au bash shell, etc.
Vous pouvez dire quel shell interactif vous utilisez le
echo $SHELL
commande, ou alternativement
env | grep -i shell
Vous pouvez changer votre shell de commande avec la chsh
commande.
Chacun a un jeu de commandes légèrement différent et une manière d'affecter des variables et son propre ensemble de constructions de programmation. Par exemple, l'instruction if-else avec bash est différente de celle du C-shell.
Cette page pourrait être intéressante car elle "traduit" entre les commandes / syntaxe bash et tcsh.
L'utilisation de la directive dans le script shell vous permet d'exécuter des programmes en utilisant un shell différent. Par exemple, j'utilise le tcsh
shell de manière interactive, mais j'exécute souvent des scripts bash en utilisant / bin / bash dans le fichier de script.
De côté:
Ce concept s'étend également à d'autres scripts. Par exemple, si vous programmez en Python, vous mettriez
#!/usr/bin/python
en haut de votre programme Python
#! $SHELL
? Est-ce que cela mettrait la bonne coquille dans le Shebang?
!#/bin/bash
directive par exemple . Il indique au système quel shell utiliser pour exécuter votre script shell.
$SHELL
ne vous dit pas nécessairement quel shell vous utilisez actuellement; il vous indique normalement votre shell par défaut . ensembles tcsh $version
et $tcsh
; ensembles bash $BASH_VERSION
. Tous les obus n'ont pas nécessairement des mécanismes similaires.
#!
ligne doit correspondre à la syntaxe du script, pas au shell interactif utilisé par celui qui exécute le script.
#!/bin/csh -f
; le-f
dit au shell de ne pas rechercher l'utilisateur.login
et.cshrc
, ce qui accélère l'exécution du script et évite les dépendances sur la configuration de l'utilisateur. (Ou mieux encore, n'écrivez pas de scripts csh.) Ne l'utilisez pas-f
pour les scripts sh ou bash; cela n'a pas la même signification.