Perché non riesco a caricare i moduli mentre eseguo il mio script bash, ma solo durante l'approvvigionamento?


13

Sto usando i moduli per controllare i pacchetti sul mio sistema e ho python/2.7.2installato come modulo. Ho un semplice eseguibile in Python python_exe.pyche chiamerò da un semplice script "guida" runit.sh. runit.shlo script ha un aspetto simile al seguente:

#!/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

Tuttavia, quando ho appena eseguito ./runit.sh, mi vende "modulo: comando non trovato". Quando source runit.sh, tuttavia, carica correttamente il modulo. Perchè è questo?

Risposte:


13

Perché il modulecomando è una funzione alias o shell (consultare " Inizializzazione del pacchetto " nel modulo (1) ). Quando dici source runit.sh, è come digitare il modulecomando direttamente nella tua shell interattiva. Ma quando dici ./runit.sh, stai eseguendo una nuova shell non interattiva. Le shell non interattive generalmente non hanno gli alias standard e le funzioni di shell impostate.

module (1) dice: “Il pacchetto Modules e il comando module sono inizializzati quando uno script di inizializzazione specifico della shell viene fornito nella shell. Lo script crea il comando del modulo , come alias o funzione shell, ... ”Se è necessario eseguire il modulecomando in uno script, trovare lo script di inizializzazione che definisce il modulecomando e sourcelo stesso dallo script.


È questa la differenza tra l'utilizzo di .bashrc e .bash_profile? Solo uno di essi ha le routine di inizializzazione per avviare il sistema del modulo per l'uso.
drjrm3,

Non sono esattamente sicuro di quello che stai chiedendo. Ma: bash fa come segue di default (queste azioni possono essere sovrascritte dalle opzioni): una shell di login legge `~ / .bash_profile` ma non ~/.bashrc, una shell interattiva che non è una shell di login (es. Cosa ottieni se digiti bashcome un comando) legge ~/.bashrcma non ~/.bash_profile, e una shell non interattiva (ad esempio, uno che esegue uno script) non legge né. ... (proseguendo)
Scott,

(Proseguendo) ... Questo è probabilmente il motivo per cui Cyrus ha suggerito #!/bin/bash -i, perché l' -iopzione rende la shell interattiva e quindi la farà leggere ~/.bashrc. IMHO, questo è eccessivo, perché la modalità interattiva potrebbe venire con un bagaglio indesiderato (come scrivere a ~/.bash_history). D'altra parte, se moduledefinito come alias (al contrario di una funzione di shell), non funzionerà in una shell non interattiva a meno che non lo dica shopt -s expand_aliases, quindi forse la risposta di Cyrus è la migliore.
Scott,

4

Sembra che la semplice invocazione della shell nel tuo sistema non erediti l'alias (o la funzione) con cui è definita module, quindi la shell non è in grado di trovarla (vedi sotto la nota con gli estratti). Prova type moduledal prompt per vedere come moduleè attualmente definito.

Essenzialmente con source è come se scrivessi ogni riga dello script dalla tastiera.
Nota che da un lato stai ereditando tutta la cronologia specifica della shell corrente ma, dall'altro, la shell corrente sarà soggetta all'effetto di tutti i lati del tuo script e della tua modulechiamata.

Sulle differenze tra l'origine di uno script e l'esecuzione è possibile leggere su SuperUser settembre 2009 o dicembre 2009 , Ubuntu febbraio 2011 , Unix agosto 2011 , Stackoverflow dicembre 2012 o in molti altri luoghi.

A questo proposito nella sezione Modulefiles c'è un avvertimento :

... Le variabili di ambiente non sono impostate quando si scarica un file di modulo. Pertanto, è possibile caricare un file di modulo e quindi scaricarlo senza che le variabili di ambiente tornino al loro stato precedente.

Quindi sembra più saggio eseguirlo in uno script .

Per realizzare quest'ultimo, posso pensare:

  1. Per usare una shell interattiva , trascurando la cronologia specifica della shell attuale, modificando il shebang del tuo script con

    #!/bin/bash -i

    Una shell interattiva legge i comandi dall'input dell'utente su un tty. Tra l'altro, una tale shell legge i file di avvio all'attivazione, visualizza un prompt e abilita il controllo dei processi per impostazione predefinita ...

  2. Se invece preferisci ereditare la storia specifica della presente shell, puoi provare a procurarla ... ma in una subshell

    ( source runit.sh )
  3. Prova a trovare l'attuale alias / funzione di modulecon type modulequindi modifica di conseguenza il tuo script. Nota: alcune variabili d'ambiente non possono essere impostate per module.
    Se lo desideri, puoi trovare gli script di inizializzazione nella directory $MODULESHOME/init/<shell>.


Commento
Come ricordato nelle domande e risposte dei moduli

Un processo figlio (script) non può modificare l'ambiente del processo padre. Un caricamento del modulo in uno script influisce solo sull'ambiente per lo script stesso. L'unico modo in cui è possibile fare in modo che uno script cambi l'ambiente corrente è di procurarsi lo script che lo legge nel processo corrente.

Quindi, se vuoi evitare di modificare l'ambiente attuale, penso che sia meglio provare a cambiare lo shebang (1) o creare lo script in una subshell (2). Non sono completamente sicuro dell'usabilità del caso (3).


Nota
Estratti dalle pagine di manuali e descrizioni dei moduli

moduleè un'interfaccia utente per il pacchetto Moduli. L' modulealias o la funzione esegue il modulecmdprogramma e fa in modo che la shell valuti l'output del comando. Il primo argomento per modulecmdspecificare il tipo di shell.

Il pacchetto Modules e il modulecomando vengono inizializzati quando uno script di inizializzazione specifico della shell viene fornito nella shell . Lo script crea il comando module, come alias o funzione shell, crea variabili d'ambiente Modules


Ma non sta cercando di influenzare l'ambiente del processo genitore; sta solo cercando di far eseguire il suo eseguibile Python dallo script . Inoltre, la tua risposta non spiega perché riceva il messaggio di errore "modulo: comando non trovato".
Scott,

@Scott Grazie. Prima ho inavvertitamente tagliato la maggior parte della risposta e pubblicato solo un frammento. Risposta riscritta.
Hastur,

1
+1.  ( source runit.sh )è una buona risposta; Non ci avevo pensato. E una buona raccolta di riferimenti.
Scott,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.