11 votes

Portée des alias dans les fonctions bash

J'utilise un script (auquel je n'ai pas accès en écriture) qui crée un tas d'alias pour configurer un environnement. Je voudrais créer une fonction bash pour configurer mon environnement, mais il semble que les alias ne survivent pas au corps de la fonction.

Voici un exemple minimal :

# aliases.sh
alias fooAlias='echo "this will never work!"'  

.

# .bashrc
function setupLotsOfThings() {
    source aliases.sh
    fooAlias
}

.

Maintenant, si je source simplement aliases.sh interactivement, les choses fonctionnent comme prévu :

[mycomputer]~/ $ source aliases.sh
[mycomputer]~/ $ fooAlias
this will never work!

Cependant, si j'appelle plutôt la fonction définie dans mon .bashrc, il ne reconnaît pas l'alias après avoir sourcé sa définition :

[mycomputer]~/ $ setupLotsOfThings
-bash: fooAlias: command not found

Qu'est-ce qui se passe ici ? Est-ce qu'il y a quelque chose qui m'échappe concernant l'étendue de la alias lorsqu'elle est utilisée dans une fonction ?

Editar: Je vais ajouter quelques détails au-delà de l'exemple minimal pour mettre en lumière ce que j'essaie d'accomplir.

Dans le cadre de mon travail, je développe et exécute de nombreux logiciels sur un cluster et/ou une grille. J'ai plusieurs projets qui nécessitent des environnements complètement différents, tels que différentes versions de gcc, des versions logicielles spécifiques, des PATH de configuration et de données, et diverses variables d'environnement. Les administrateurs fournissent les scripts pour configurer diverses choses, généralement en définissant des fonctions ou des alias scripts, qui invoquent d'autres fonctions ou alias ou exécutent divers scripts. Pour moi, c'est une boîte noire.

J'aimerais configurer mes différents environnements avec une seule commande. Actuellement, je fais quelque chose comme :

[mycomputer]~/ $ source /some/environment/setup/script.sh
[mycomputer]~/ $ aliasToSetupSomeSoftwareVersion    #this was defined in the above
[mycomputer]~/ $ anotherAliasForOtherSoftware
[mycomputer]~/ $ source /maybe/theres/another/script.sh
[mycomputer]~/ $ runSomeOtherSetup      # this was defined in the new script

Ces commandes doivent généralement être exécutées dans l'ordre. Mon idée de base était de simplement copier les lignes ci-dessus dans un bloc de fonctions, mais comme le montre l'exemple original, cela ne fonctionne tout simplement pas. Les solutions de rechange sont les bienvenues !

12voto

Mohsin Points 11

Une autre solution consiste à coller ces commandes dans un fichier texte au lieu d'un bloc fonctionnel. Quelque chose comme :

## This is needed to make the sourced aliases available
## within the script.
shopt -s expand_aliases

source /some/environment/setup/script.sh
aliasToSetupSomeSoftwareVersion
anotherAliasForOtherSoftware
source /maybe/theres/another/script.sh
runSomeOtherSetup

Sauvegarder cela comme setup1.sh où vous voulez. L'astuce consiste ensuite à source ce fichier, et non l'exécuter :

$ source setup1.sh

Cela exécutera les alias qui sont dans le script et les rendra également disponibles à votre script actuel.

Vous pouvez simplifier encore plus le processus en ajoutant cet élément à votre liste de contrôle. .bashrc :

alias setupLotsOfThings="source setup1.sh"

Maintenant vous pouvez simplement exécuter setupLotsOfThings et obtenir le comportement que vous vouliez de la fonction.


Explication

Il y a deux problèmes ici. Premièrement, les alias ne sont pas disponibles pour la fonction dans laquelle ils sont déclarés mais seulement une fois que cette fonction est sortie et deuxièmement, les alias ne sont pas disponibles dans les scripts. Les deux sont expliqués dans la même section de man bash :

Les alias ne sont pas développés lorsque le Shell n'est pas interactif, sauf si l'option expand_aliases Shell soit définie en utilisant shopt (voir la description de shopt sous Shell COMMANDES BUILTINES ci-dessous).

Les règles concernant la définition et l'utilisation des alias sont quelque peu confuses. Bash lit toujours au moins une ligne complète complète avant d'exécuter l'une des commandes de cette ligne. cette ligne. Les alias sont développés lorsqu'une commande est lue, et non pas lorsqu'elle est est exécutée. Par conséquent, une définition d'alias apparaissant sur la même ligne qu'une autre commande ne prend pas effet avant la lecture de la prochaine ligne d'entrée suivante soit lue. Les commandes qui suivent la définition de l'alias sur cette ligne ne sont pas affectées par le nouvel alias. Ce comportement est également un problème lorsque des fonctions sont exécutées. Les alias sont développés lorsqu'une définition de fonction est lue, et non lorsque la fonction est exécutée, parce qu'une définition de fonction est elle-même une commande composée. Par conséquent, les alias définis dans une fonction ne sont pas
disponible jusqu'à ce que cette fonction soit exécutée.
Pour être sûr, mettez toujours les définitions d'alias sur une ligne séparée, et n'utilisez pas alias dans les commandes communes.

Ensuite, il y a la différence entre l'exécution et l'approvisionnement d'un fichier. Fondamentalement, l'exécution d'un script le fait fonctionner dans un script séparé tandis que le sourcing le fait fonctionner dans le script courant. Donc, le sourcing setup.sh rend les alias disponibles pour le Shell parent alors que l'exécuter comme un Shell ne le ferait pas.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X