Pour un script csh, vous devez utiliser #!/bin/csh -f; le -fdit au shell de ne pas rechercher l'utilisateur .loginet .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 -fpour les scripts sh ou bash; cela n'a pas la même signification.
@Kolob Canyon, vous n'avez pas besoin de le faire, mais cela peut aider certains éditeurs avec la coloration syntaxique (bien qu'il existe généralement d'autres moyens pour obtenir la même chose): unix.stackexchange.com/a/88730/193985
Braham Snyder
42
La #!ligne indique au noyau (spécifiquement, l'implémentation de l' execveappel 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ù ./scriptcommence par, disons, #! /usr/bin/perlcomme 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/shpour écrire un script destiné à être interprété par sh.
La #!ligne n'est traitée que si vous appelez directement le script ( ./scriptsur la ligne de commande); le fichier doit également être exécutable ( chmod +x script). Si vous faites, sh ./scriptla #!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é:
Le #!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.
Le chemin après #!doit être un chemin absolu (commence par /). Il ne peut pas contenir de caractères d'espace, de tabulation ou de nouvelle ligne.
Il est judicieux, mais pas obligatoire, de mettre un espace entre le #!et le /. N'y mettez pas plus d'un espace.
Vous ne pouvez pas mettre de variables shell sur la #!ligne, elles ne seront pas développées.
Vous pouvez placer un argument de ligne de commande après le chemin absolu, séparé de celui-ci par un seul espace. Comme le chemin absolu, cet argument ne peut pas contenir de caractères d'espace, de tabulation ou de nouvelle ligne. Parfois, c'est nécessaire pour faire fonctionner les choses ( #! /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.
Certaines personnes vous diront d'utiliser à la #! /usr/bin/env interpreterplace de #! /absolute/path/to/interpreter. C'est presque toujours une erreur. Cela rend le comportement de votre programme dépendant de la $PATHvariable de l'utilisateur qui appelle le script. Et tous les systèmes ne l'ont pas fait enven premier lieu.
Les programmes qui ont besoin setuidou les setgidprivilèges ne peuvent pas utiliser #!; ils doivent être compilés en code machine. (Si vous ne savez pas ce que setuidc'est, ne vous inquiétez pas.)
En ce qui concerne csh, cela se rapporte à shpeu près à ce que le substitut de thé avancé Nutrimat fait au thé. Il a (ou plutôt eu; les implémentations modernes shont 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 cshparent comme shell de connexion, basculez vers bashou zsh, afin que le langage de commande interactif soit le même que le langage de script que vous apprenez.
Les versions récentes de Linux permettent à l'interpréteur spécifié d'être un script. Il est courant d'omettre l'espace après le #!; 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/envhack.
Keith Thompson
@KeithThompson J'ai l'impression que Linux est la seule variante Unix courante qui permet à l'interpréteur d'être un script, donc ce n'est toujours pas quelque chose sur lequel s'appuyer. Depuis que j'ai écrit ceci, j'ai moi-même rencontré une situation où #!/usr/bin/envétait la bonne chose, mais je reste d'avis que c'est presque toujours une mauvaise idée.
zwol
4
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/cshfait référence au C-shell, /bin/tcshau t-shell, /bin/bashau 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 chshcommande.
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 tcshshell 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
Alors, est-ce nécessaire? Comment savoir quel shell j'utilise réellement?
One Two Three
Donc, si j'écris les scripts pour quelqu'un à utiliser sur leur machine, et je ne sais pas quel shell ils utilisent. (Cette personne, malheureusement, n'a aucune idée de ce genre de choses, donc tout ce qu'elle peut faire est d'exécuter le script sans rien changer). Puis-je faire quelque chose comme #! $SHELL? Est-ce que cela mettrait la bonne coquille dans le Shebang?
One Two Three
1
@OneTwoThree La plupart des systèmes ont les shells standard, si vous écrivez un script bash ou csh, tout ira bien. Le shell qu'ils utilisent de manière interactive n'a pas d' importance, c'est la beauté de la !#/bin/bashdirective par exemple . Il indique au système quel shell utiliser pour exécuter votre script shell.
Levon
La valeur de $SHELLne vous dit pas nécessairement quel shell vous utilisez actuellement; il vous indique normalement votre shell par défaut . ensembles tcsh $versionet $tcsh; ensembles bash $BASH_VERSION. Tous les obus n'ont pas nécessairement des mécanismes similaires.
Keith Thompson
1
@OneTwoThree: La #!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.Réponses:
Ceci est connu comme un
Shebang
:http://en.wikipedia.org/wiki/Shebang_(Unix)
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 source
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 deoù
./script
commence par, disons,#! /usr/bin/perl
comme si la ligne de commande avait effectivement étéOu, comme vous l'avez vu, vous pouvez utiliser
#! /bin/sh
pour écrire un script destiné à être interprété parsh
.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. (Faitesgrep '^#!' /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 faitenv
en premier lieu.setuid
ou lessetgid
privilèges ne peuvent pas utiliser#!
; ils doivent être compilés en code machine. (Si vous ne savez pas ce quesetuid
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 modernessh
ont rattrapé) un certain nombre d'avantages par rapportsh
à une utilisation interactive, mais l'utiliser (ou son descendanttcsh
) 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 sursh
. Si vous utilisez uncsh
parent comme shell de connexion, basculez versbash
ouzsh
, afin que le langage de commande interactif soit le même que le langage de script que vous apprenez.la source
#!
; 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
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
la source
#! $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.