J'ai un projet composé d'environ 20 petits .sh
fichiers. Je les nomme «petits» car généralement, aucun fichier ne contient plus de 20 lignes de code. J'ai adopté une approche modulaire car je suis donc fidèle à la philosophie Unix et il est plus facile pour moi de maintenir le projet.
Au début de chaque .sh
fichier, je mets #!/bin/bash
.
Autrement dit, je comprends que les déclarations de script ont deux objectifs:
- Ils aident l'utilisateur à se rappeler quel shell est nécessaire pour exécuter le fichier (par exemple, après quelques années sans utiliser le fichier).
- Ils s'assurent que le script ne s'exécute qu'avec un certain shell (Bash dans ce cas) pour éviter un comportement inattendu au cas où un autre shell serait utilisé.
Quand un projet commence à croître, disons de 5 fichiers à 20 fichiers ou de 20 fichiers à 50 fichiers (pas dans ce cas mais juste pour le démontrer), nous avons 20 lignes ou 50 lignes de déclarations de script. J'avoue, même si cela peut être drôle pour certains, cela me semble un peu redondant d'utiliser 20 ou 50 à la place, disons seulement 1 par projet (peut-être dans le fichier principal du projet).
Existe-t-il un moyen d'éviter cette redondance alléguée de 20 ou 50 ou un nombre beaucoup plus élevé de lignes de déclarations de script en utilisant une déclaration de script "globale", dans un fichier principal?
la source
/bin/bash -x "$script"
Réponses:
Même si votre projet peut désormais être composé uniquement de 50 scripts Bash, il commencera tôt ou tard à accumuler des scripts écrits dans d'autres langages tels que Perl ou Python (pour les avantages que ces langages de script ont que Bash n'a pas).
Sans une
#!
ligne appropriée dans chaque script, il serait extrêmement difficile d'utiliser les différents scripts sans savoir également quel interprète utiliser. Peu importe que chaque script soit exécuté à partir d'autres scripts , cela ne fait que déplacer la difficulté des utilisateurs finaux aux développeurs. Aucun de ces deux groupes de personnes ne devrait avoir besoin de savoir dans quelle langue un script a été écrit pour pouvoir l'utiliser.Les scripts shell exécutés sans
#!
ligne et sans interprète explicite sont exécutés de différentes manières selon le shell qui les appelle (voir par exemple la question Quel interpréteur shell exécute un script sans shebang? Et surtout la réponse de Stéphane ), ce qui n'est pas ce que vous voulez dans un environnement de production (vous voulez un comportement cohérent, et peut-être même une portabilité).Les scripts exécutés avec un interpréteur explicite seront exécutés par cet interprète indépendamment de ce que
#!
dit la ligne. Cela entraînera des problèmes plus loin si vous décidez de réimplémenter, par exemple, un script Bash en Python ou dans tout autre langage.Vous devez dépenser ces frappes supplémentaires et toujours ajouter une
#!
ligne à chaque script.Dans certains environnements, il existe des textes juridiques passe-partout multi-paragraphes dans chaque script de chaque projet. Soyez très heureux que ce soit seulement une
#!
ligne qui semble "redondante" dans votre projet.la source
#!
ligne dès que le fichier a une autorisation exécutable et n'est pas chargé par un interprète, mais par le shell. Autrement dit,/path/to/myprog.pl
exécute un programme perl si la#!
ligne est présente (pointant vers l'interpréteur perl) et que le fichier a la permission exec.Vous comprenez mal le point de
#!
. Il s'agit en fait d'une directive adressée au système d'exploitation pour exécuter ce programme sous l'interpréteur défini.Ainsi, un script pourrait être
#!/usr/bin/perl
et le programme résultant peut être exécuté en tant que./myprogram
et l'interpréteur perl pourrait être utilisé. De même#!/usr/bin/python
, un programme s'exécuterait sous python.Ainsi, la ligne
#!/bin/bash
indique au système d'exploitation d'exécuter ce programme sous bash.Voici un exemple:
Donc, bien que mon shell soit ksh, le programme "x" s'exécute sous bash à cause de la
#!
ligne, et nous pouvons le voir explicitement dans la liste des processus.la source
ps -aux
peut donner un avertissement,ps
donne l'avertissementWarning: bad syntax, perhaps a bogus '-'?
.ps
prend en charge la syntaxe des arguments BSD et UXIX .-aux
est faux UNIX Stephen signifie probablement ceaux
qui est correct BSDps
montre l'appel debash
) et non la syntaxe explicite; (2)ps -aux
fonctionne parfaitement sur CentOS 7 et Debian 9 sans avertissements; ce cut'n'paste était exactement la sortie de ma machine; toute la discussion sur la-
nécessité ou non s'applique aux anciennes versions de Linux procps, pas aux versions actuelles.Sur
.sh
Ce qui est mauvais, c'est
.sh
à la fin du nom de fichier.Imaginez que vous réécrivez l'un des scripts en python.
Eh bien maintenant, vous devez changer la première ligne pour que
#!/usr/bin/python3
ce ne soit pas si mal, car vous avez également dû changer toutes les autres lignes de code dans le fichier. Cependant, vous devez également changer le nom du fichier deprog.sh
àprog.py
. Et puis vous devez trouver partout dans les autres scripts, et tous vos scripts utilisateur (ceux dont vous ne saviez même pas qu'ils existaient), et les changer pour utiliser le nouveau script.sed -e 's/.sh/.py/g'
peut aider ceux que vous connaissez. Mais maintenant, votre outil de contrôle des révisions montre un changement dans de nombreux fichiers non liés.Vous pouvez également le faire à la manière Unix et
prog
ne pas nommer le programmeprog.sh
.Sur
#!
Si vous avez le bon
#!
, et définissez l'autorisation / mode pour inclure exécuter. Ensuite, vous n'avez pas besoin de connaître l'interprète. L'ordinateur le fera pour vous.Pour les systèmes non GNU, lisez le manuel de
chmod
(et apprenez l'octal), peut-être le lirez quand même.la source
.image
pour les photos..audio
pour le son, etc. Vous dites ainsi de quoi il s'agit mais pas de l'implémentation / de l'encodage.launch-missiles
ou quedelete-project-and-make-manager-pissed
je ne veux pas "simplement l'exécuter" alors que j'étais seulement curieux de connaître la langue :)file
commande. il reconnaît la plupart des types de fichiers.Il vaut probablement la peine de souligner que c'est tout à fait faux. La ligne de hachage ne vous empêche en aucun cas d'essayer d'alimenter le fichier vers un interpréteur / interpréteur de commandes incorrect:
(ou similaire avec
awk -f array.sh
etc.)Mais dans tous les cas, une autre approche de la modularité serait de définir des fonctions shell dans les fichiers, une fonction par fichier, si vous voulez, puis
source
les fichiers du programme principal. De cette façon, vous n'auriez pas besoin de hashbangs: ils seraient traités comme tous les autres commentaires, et tout fonctionnerait en utilisant le même shell. L'inconvénient serait que vous auriez besoinsource
des fichiers avec les fonctions (par exemplefor x in functions/*.src ; do source "$x" ; done
), et ils s'exécuteraient tous en utilisant le même shell, donc vous ne pourriez pas remplacer directement l'un d'eux par une implémentation Perl.la source
Il y a - cela s'appelle la portabilité ou la conformité POSIX. Efforcez-vous de toujours écrire des scripts de manière portable et sans shell, source uniquement à partir d'un script qui utilise
#!/bin/sh
ou lorsque vous utilisez de manière/bin/sh
interactive (ou au moins un shell compatible POSIX tel queksh
).Cependant, les scripts portables ne vous épargnent pas:
/bin/sh
script aveccsh
.Si je peux exprimer mon opinion, «éviter la redondance» en éliminant
#!
est un mauvais objectif. L'objectif doit être des performances cohérentes et en fait un script de travail qui fonctionne et qui considère les cas d'angle, suit certaines règles générales comme ne pas analyser les ls ou toujours citer des variables, sauf si vous avez besoin de séparer les mots .Ils ne sont vraiment pas destinés à l'utilisateur - ils sont destinés au système d'exploitation pour exécuter l'interpréteur approprié. "Propre" dans ce cas, signifie que OS trouve ce qui se trouve dans shebang; si le code en dessous pour un mauvais shell - c'est la faute de l'auteur. En ce qui concerne la mémoire utilisateur, je ne pense pas que "l'utilisateur" de programmes tels que Microsoft Word ou Google Chrome ait jamais eu besoin de savoir dans quels programmes linguistiques sont écrits; les auteurs peuvent avoir besoin.
Là encore, les scripts écrits de manière portative peuvent éliminer le besoin de même se souvenir du shell que vous avez utilisé à l'origine, car les scripts portables devraient fonctionner dans n'importe quel shell compatible POSIX.
Ils ne le font pas. Ce qui empêche réellement un comportement inattendu, c'est l'écriture de scripts portables.
la source
La raison pour laquelle vous devez mettre
#!/bin/bash
en haut de chaque script est que vous l'exécutez comme un processus distinct.Lorsque vous exécutez un script en tant que nouveau processus, le système d'exploitation voit qu'il s'agit d'un fichier texte (par opposition à un exécutable binaire) et a besoin de savoir quel interpréteur exécuter. Si vous ne le dites pas, le système d'exploitation ne peut que deviner, en utilisant son paramètre par défaut (qu'un administrateur peut modifier). Ainsi, la
#!
ligne (plus l'ajout d'autorisations exécutables, bien sûr) transforme un simple fichier texte en un exécutable qui peut être exécuté directement, avec la certitude que le système d'exploitation sait quoi en faire.Si vous souhaitez supprimer la
#!
ligne, vos options sont les suivantes:Exécutez le script directement (comme vous le faites maintenant) et espérez que l'interpréteur par défaut correspond au script - vous êtes probablement en sécurité sur la plupart des systèmes Linux, mais pas portable sur d'autres systèmes (par exemple Solaris), et il peut être changé en n'importe quoi (je pourrais même le configurer pour qu'il s'exécute
vim
sur le fichier!).Exécutez le script à l'aide de
bash myscript.sh
. Cela fonctionne bien, mais vous devez spécifier le chemin d'accès au script, et c'est compliqué.Sourcez le script en utilisant
. myscript.sh
, qui exécute le script dans le processus d'interpréteur en cours (c'est-à-dire pas en tant que sous-processus). Mais cela nécessitera presque certainement des modifications à vos scripts et les rendra moins modulaires / réutilisables.Dans les cas 2 et 3, le fichier n'a pas besoin (et ne devrait pas avoir) d'autorisations d'exécution, et lui donner un
.sh
(ou.bash
) suffixe est une bonne idée.Mais aucune de ces options ne semble bonne pour votre projet, car vous avez dit que vous vouliez garder vos scripts modulaires (=> indépendants et autonomes), vous devriez donc garder votre
#!/bin/bash
ligne en haut des scripts.Dans votre question, vous avez également dit que vous suiviez la philosophie Unix. Si c'est vrai, alors vous devriez apprendre à quoi
#!
sert vraiment la ligne et continuer à l'utiliser dans chaque script exécutable!la source
then you should learn what the #! line is really for, and keep using it in every executable script!
. On peut suivre la philosophie U. jusqu'à un certain point de connaissance. Après toutes ces réponses, j'ai compris pourquoi il pouvait être inclus dans ce terme. Je suggère de modifier la réponse, en la remplaçant par "Voir le shebang comme une partie interne de la philosophie Unix que vous respectez et adoptez".