Bonne façon de distribuer les scripts shell

8

Quelle est la manière la plus appropriée de distribuer des scripts shell, si les comportements des shells peuvent être modifiés par setet sont donc imprévisibles?

Par exemple, rm *.txtne serait pas exécuté comme prévu sur les environnements dans lesquels il set -fa été exécuté. Comment dois-je m'assurer que rm *.txttous les fichiers texte d'un répertoire actuel sont supprimés dans tous les environnements?

Comment dois-je m'assurer que les scripts shell s'exécuteront comme prévu avant de les distribuer en général?

hoge
la source
shell_state=$(set +o) ... script ...eval "$shell_state"
mikeserv
Vous pouvez exécuter ces commandes en haut du script lui-même ou modifier le #!pour spécifier les options de shell que vous souhaitez.
HalosGhost

Réponses:

6

Les scripts shell sont normalement traités comme s'ils étaient les mêmes que tout autre type de fichier exécutable, tels que les binaires, les scripts Python, les scripts Perl ou tout autre type de script. Ils ont un shebang en haut qui dirige le noyau pour les exécuter à travers le shell. Ils devraient être invoqués de la même manière que toute autre commande.

En tant que tel, un nouveau shell est démarré chaque fois que le script est appelé, et tous les paramètres tels que ceux set -fprésents dans le shell appelant ou dans toute autre instance de shell du système ne sont pas pertinents.

Bien sûr, il est possible pour les utilisateurs de source votre script au lieu de l'exécuter, par exemple comme ceci:

. /path/to/your/script

ou pour l'exécuter dans un shell qui a des paramètres non par défaut comme celui-ci:

sh -f /path/to/your/script

mais ceux-ci ne sont pas considérés comme des moyens normaux ou d'invoquer votre script, et les utilisateurs qui le font devraient s'attendre à ce qu'ils obtiennent en conséquence.

Notez qu'il y a des scripts qui sont destinés à être sourcés, non exécutés, car leur but est de faire des choses comme changer le cwd ou définir des variables d'environnement qui doivent être reflétées dans l'environnement du shell de sourcing, mais ce sont en minorité et cela se fait généralement dans le cadre d'un protocole convenu. Ces fichiers peuvent être considérés plus comme des "plugins" pour n'importe quel système dont ils s'attendent à provenir, pas tant que des scripts indépendants. Par exemple, les fichiers /etc/rc*.ddont le nom se termine .shpar proviennent du sous-système de script de démarrage et ne sont pas exécutés, et il est documenté que c'est ce qui se produira si vous placez un fichier portant un tel nom dans/etc/rc*.det quand c'est fait, c'est fait exprès. La convention de nommer les fichiers destinés à provenir au lieu d'être exécutés de cette manière est également suivie ailleurs, mais pas universellement.

Il est vrai que les fichiers destinés à provenir de cette manière doivent prendre soin des paramètres qui pourraient être présents dans l'environnement de leur appelant et qui pourraient affecter le comportement du shell, mais le protocole convenu devrait alors idéalement promettre un environnement d'exécution prévisible.

Celada
la source
1
zsha une fonctionnalité qui permet de restaurer les options dans un ensemble connu dans un contexte local ( emulate -L zsh) qui est largement utilisé dans toutes les extensions livrées avec zsh et écrites en code zsh. Voyez comment le système d'achèvement de bash échoue lamentablement si vous définissez certaines options comme failglob.
Stéphane Chazelas
Certains shells lisent votre fichier de personnalisation même lorsqu'ils sont invoqués pour interpréter des scripts. C'est pourquoi vous utilisez généralement #! /bin/csh -fau lieu de #! /bin/cshpar exemple.
Stéphane Chazelas
@ StéphaneChazelas Haha, oui en effet. Bien sûr, cela fait partie des raisons pour lesquelles l' utilisation de csh est une mauvaise idée , non? :-) Mais je suppose que zsh a ça aussi, sous la forme de zshenv. Faites attention à ce que vous mettez zshenvpour cette raison!
Celada
@ StéphaneChazelas au fait, ce n'est pas la première fois que tu m'apprends quelque chose que je ne savais pas ( emulate -Ldans ce cas) en commentant une de mes réponses, et je l'apprécie.
Celada
Eh bien, ~/.zshenv(où vous voulez forcer les paramètres (généralement les vars env) pour tous les zsh (interactifs ou non) invoqués sous votre nom, et généralement non utilisés sauf pour contourner un autre problème non zsh) est séparé de ~/.zshrc(l'interactif shell de personnalisation), c'est donc une fonctionnalité, pas un bug. (vous pouvez utiliser zsh -f) Un bogue survient lorsque certains shells bash non interactifs lisent votre ~/.bashrc(comme sur ssh et vous devez ajouter du code pour éviter cela), ou certains bash interactifs (ceux de connexion) ne le lisent pas (et encore une fois, vous devez ajouter du code dans votre ~/.bash_profilepour contourner ce problème).
Stéphane Chazelas