web-dev-qa-db-fra.com

Pourquoi ne puis-je pas charger des modules pendant l'exécution de mon script bash, mais uniquement lors de son sourcing?

J'utilise modules pour contrôler les packages sur mon système et j'ai python/2.7.2 installé en tant que module. J'ai simple python exécutable python_exe.py que je vais appeler à partir d'un simple script "de conduite" runit.sh. runit.sh le script ressemble à ceci:

#!/bin/bash
module load python/2.7.2
arg1=myarg1
arg2=15
arg3=$5
/path/to/python_exe.py -a $arg1 -b $arg2 -c $arg3

Mais quand je lance juste ./runit.sh, il me vend "module: commande introuvable". Quand je source runit.sh, cependant, il charge correctement le module. Pourquoi est-ce?

13
drjrm3

Parce que la commande module est un alias ou une fonction Shell (voir "Initialisation du package"in module (1) ). Lorsque vous dites source runit.sh, c'est comme taper la commande module directement dans votre shell interactif. Mais quand vous dites ./runit.sh, vous exécutez un nouveau shell non interactif. Les shells non interactifs n'ont généralement pas les alias standard et les fonctions Shell configurés.

module (1) dit, "Le package Modules et la commande module sont initialisés lorsqu'un script d'initialisation spécifique à Shell est obtenu dans le Shell. Le script crée la commande du module , soit en tant qu'alias, soit en tant que fonction Shell,… "Si vous devez exécuter la commande module dans un , recherchez le script d'initialisation qui définit la commande module et source à partir du script.

14
Scott

Il semble que la simple invocation du Shell dans votre système n'hérite pas de l'alias (ou de la fonction) avec lequel est défini module, donc le Shell n'est pas en mesure de le trouver (voir ci-dessous la note avec les extraits ). Essayez type module depuis l'invite pour voir comment module il est actuellement défini.

Essentiellement avec source c'est comme si vous écriviez chaque ligne du script depuis le clavier.
Notez que d'un côté vous héritez de tout l'historique spécifique du Shell actuel mais, de l'autre, le Shell actuel sera soumis à tous les effets de votre script et à l'invocation de module .

À propos des différences entre la source d'un script et son exécution , vous pouvez lire sur SuperUser Sep 2009 ou Dec 2009 , Ubuntu février 2011 , Unix août 2011 , Stackoverflow décembre 2012 ou dans de nombreux autres endroits.

À cet égard, dans les Modulefiles section il y a un avertissement :

... Les variables d'environnement ne sont pas définies lors du déchargement d'un fichier de modules. Ainsi, il est possible de charger un modulefile puis de le décharger sans que les variables d'environnement reviennent à leur état antérieur.

Il semble donc plus judicieux de l'exécuter dans un script .

Pour accomplir ce dernier je pense:

  1. Pour utiliser un Shell interactif , en négligeant l'historique spécifique du Shell actuel, en modifiant le Shebang de votre script avec

    #!/bin/bash -i
    

    Un shell interactif lit les commandes de l'entrée utilisateur sur un tty. Entre autres choses, un tel Shell lit les fichiers de démarrage lors de l'activation, affiche une invite et active le contrôle des travaux par défaut ...

  2. Si à la place vous préférez hériter de l'histoire spécifique du Shell actuel, vous pouvez essayer de la source ... mais dans un sous-shell

    ( source runit.sh )
    
  3. Essayez de trouver l'alias/la fonction actuelle de module avec type module puis modifiez en conséquence votre script. Notez que certaines variables d'environnement ne peuvent pas être définies pour module.
    Si vous le souhaitez, vous pouvez trouver les scripts d'initialisation dans le répertoire$MODULESHOME/init/<Shell>.


Commentaire
Comme rappelé dans le Q&A des modules

Un processus enfant (script) ne peut pas modifier l'environnement de processus parent. Une charge de module dans un script affecte uniquement l'environnement du script lui-même. La seule façon dont un script peut changer l'environnement actuel est de trouver le script qui le lit dans le processus en cours.

Donc, si vous voulez éviter de modifier l'environnement actuel, je pense qu'il vaut mieux essayer de changer le Shebang (1) ou source le script dans un sous-shell (2). Je ne suis pas complètement sûr de l'utilisabilité du boîtier (3).


Remarque
Extraits des pages de manuel et de description de modules

module est une interface utilisateur du package Modules. L'alias ou la fonction module exécute le programme modulecmd et demande au shell d'évaluer la sortie de la commande. Le premier argument de modulecmd spécifie le type de Shell.

Le package Modules et la commande module sont initialisés lorsqu'un script d'initialisation spécifique au Shell est fourni dans le Shell . Le script crée la commande module, sous forme d'alias ou de fonction Shell, crée des variables d'environnement Modules

4
Hastur