Pourquoi bash analyse-t-il / exécute-t-il même des éléments placés dans la variable d'environnement?

9

Le bug shellshock dans bash fonctionne au moyen de variables d'environnement. Honnêtement, j'ai été surpris par le fait qu'il existe une telle fonctionnalité comme:

"transmission des définitions de fonction via env vars"

Par conséquent, cette question, même si elle n'est peut-être pas parfaitement formulée, est de demander un exemple ou un cas dans lequel il serait nécessaire d'avoir cette fonctionnalité?

Prime. Les autres coques zsh, dash etc. ont-elles également cette fonctionnalité?

l'humanité et la paix
la source
Il utilise les vars env pour transmettre les définitions de fonction. Que voulez-vous dire par "Pourquoi ne maintient-il pas simplement les variables d'environnement disponibles / accessibles?" ?
Anthon
@Anthon Merci pour le commentaire. Je devrais peut-être être plus clair et reformuler. Pour quelle raison est-il nécessaire de pouvoir transmettre des définitions de fonctions via des vars env?
humanityANDpeace
1
Je ne suis pas sûr à 100% mais je pense que c'est par exemple la façon dont GNU parallelobtient les définitions de fonction distribuées s'il invoque plusieurs instances bash. Si ce n'est pas de cette façon, il faudrait les écrire dans un fichier, que chaque instance invoquée lit et ensuite vous devez faire face à des problèmes comme quand ce fichier peut être supprimé.
Anthon
2
ce fil a une histoire. les fonctions exportées, cependant, sont folles . si vous voulez qu'un nouveau shell hérite des anciennes commandes exécutables du shell, vous .dotsourcez le même fichier que l'ancien shell. thats comment son fait - et cela a du sens - ou vous alimentez le nouveau shell le fichier en entrée lors de l' execing. une fois qu'il est lu une fois le fichier mis en cache par le noyau de toute façon.
mikeserv
@mikeserv Est-ce que je comprends bien, qu'une grande partie du shellshock est liée à cette fonctionnalité qui n'est pas si essentielle de toute façon?
humanityANDpeace

Réponses:

4

Lorsqu'un script appelle un autre script, les variables du script parent peuvent être exportées, puis elles seront visibles dans le script enfant. L'exportation de fonctions est une généralisation évidente: exportez la fonction du parent, rendez-la visible chez l'enfant.

L'environnement est le seul moyen pratique pour un processus de transmettre des données arbitraires à ses enfants. Les données doivent être rassemblées en chaînes qui ne contiennent pas d'octets nuls, ce qui n'est pas une difficulté pour les fonctions shell. Il existe d'autres méthodes potentielles, telles que des blocs de mémoire partagée ou des fichiers temporaires transmis via des descripteurs de fichiers, mais ceux-ci pourraient provoquer des problèmes avec des programmes intermédiaires qui ne savent pas quoi faire avec eux ou les fermeraient. Les programmes s'attendent à s'exécuter dans un environnement qui contient des variables qu'ils ne connaissent pas ou dont ils ne se soucient pas, donc ils ne vont pas les écraser ni les effacer.

Le choix d'utiliser le nom de la fonction comme nom de la variable d'environnement est étrange. D'une part, cela signifie qu'une variable exportée se heurte à une fonction exportée du même nom.

Les fonctions exportées sont une ancienne fonctionnalité. Des fonctions ont été ajoutées dans le shell Bourne dans SVR2 , et des fonctions exportées dans le shell version 8 publiées la même année (1984). Dans ce shell, les variables et les fonctions utilisaient le même espace de noms. Je ne sais pas comment a fonctionné l'exportation de fonctions. Le shell Heirloom est basé sur une variante Bourne qui a des fonctions mais ne les exporte pas.

ATT ksh prend soi-disant en charge l'exportation de fonctions, mais en regardant la source ou en jouant avec, je ne peux pas voir que c'est le cas, à partir de ksh93u.

env -i /usr/bin/ksh -c 'f=variable; f () { echo function; }; typeset -fx f; /usr/bin/env; ksh -c f'
_=*25182*/usr/bin/env
PWD=/home/gilles
SHLVL=1
A__z="*SHLVL
ksh: f: not found

Les clones du domaine public de Ksh (pdksh, mksh), dash et zsh ne prennent pas en charge les fonctions d'exportation.

Gilles 'SO- arrête d'être méchant'
la source
1
Merci! Donc, sans exporter les fonctions, la fonctionnalité est perdue, mais il y a des shell comme dash, zsh et pdksh etc. qui manquent de cette fonctionnalité, est-ce que je lis bien?
humanityANDpeace
Mais quand j'exporte une fonction en bash, elle va dans une variable comme BASH_FUNC_f%%=() { echo hi }. Pourquoi bash analyserait-il d'autres variables d'environnement? Pourquoi serait-il même analysé BASH_FUNC_g%%lorsque je n'appelle que f? (Apparemment, avant le shellshock, la variable d'environnement vient d'être appelée fou g- mais je me demande toujours pourquoi gaurait été analysée si je n'appelais jamais gdans mon script)
Metamorphic
@Met Il doit examiner toutes les variables d'environnement pour déterminer celles qui sont des définitions de fonction. Il pourrait mémoriser ce fait et éviter d'analyser le code d'une fonction jusqu'à la première utilisation, mais ce serait une complexité supplémentaire pour très peu de gain. Il est plus facile d'avoir un seul type de fonction et non deux ("fonction normale" et "fonction d'une variable d'environnement qui a besoin d'un peu d'analyse").
Gilles 'SO- arrête d'être méchant'
Pas clair. Je suggère que la chose évidente à faire aurait été, lorsque j'exécute quelque chose appelé f, (1) de rechercher une fonction shell appelée f, (2) de rechercher une variable d'environnement appelée fet d'essayer de l'analyser, (3) de vérifier chaque PATHcomposant d'un exécutable appelé f. Comment l'analyse de chaque variable d'environnement en tant que code shell, au démarrage du shell, peut-elle sembler une conception moins compliquée?
Metamorphic
@Metamorphic Vous proposez d'ajouter une autre étape qui doit être effectuée à chaque commande. Vous devrez également ajouter une autre étape lors de la définition ou de la définition de fonctions (après unset -f foo, bash ne doit plus rechercher de définition de fonction foodans l'environnement), lors de la liste des fonctions (comment gérez-vous declare -fautre que la lecture de toutes les variables d'environnement?) , et tout ce à quoi je ne pense pas. Votre conception ne semble plus facile parce que vous en avez omis la plupart. En revanche, tout faire au démarrage est un seul morceau de code et après cela, tout fonctionne.
Gilles 'SO- arrête d'être méchant'