web-dev-qa-db-ja.com

bashスクリプトの実行中にモジュールを読み込めないのはなぜですか?

私は modules を使用してシステム上のパッケージを制御しており、python/2.7.2モジュールとしてインストールされています。簡単なpython実行可能ファイルpython_exe.py簡単な「運転」スクリプトから呼び出すつもりですrunit.shrunit.shスクリプトは次のようになります。

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

しかし、私が./runit.sh、「モジュール:コマンドが見つかりません」を販売しています。私がsource runit.shただし、モジュールは正しく読み込まれます。どうしてこれなの?

13
drjrm3

moduleコマンドはエイリアスまたはシェル関数です(「パッケージの初期化" module(1) )。source runit.shmoduleコマンドをインタラクティブシェルに直接入力するようなものです。しかし./runit.sh、新しい非インタラクティブシェルを実行しています。非対話型シェルには、通常、標準のエイリアスとシェル関数が設定されていません。

module(1) は、「モジュールパッケージとmoduleコマンドは、シェル固有の初期化スクリプトが提供されるときに初期化されますシェルに。スクリプトは、エイリアスまたはシェル関数としてmoduleコマンドを作成します…” moduleコマンドをスクリプトから、moduleコマンドとsourceを定義する初期化スクリプトをスクリプトから見つけます。

14
Scott

システムでのシェルの単純な呼び出しは、moduleが定義されているエイリアス(または関数)を継承しないため、シェルはそれを見つけることができません(以下の抜粋を参照してください)。 )。プロンプトからtype moduleを試して、現在どのようにmoduleが定義されているかを確認してください。

基本的にsourceを使用すると、キーボードからスクリプトの各行を書き込むようなものです。
一方の側では現在のシェルのすべての特定の履歴を継承していますが、もう一方の側では、現在のシェルはスクリプトとmodule呼び出しのすべての副次的な影響を受けることに注意してください。

スクリプトのソースと実行の違いについて違いについてSuperUser Sep 2009 または Dec 2009 、Ubuntu 2011年2月 、Unix 2011年8月 、Stackoverflow 2012年12月 または他の多くの場所。

これに関して、Modulefilessectionwarning

...環境変数は、モジュールファイルをアンロードするときに設定解除されます。したがって、環境変数を以前の状態に戻さなくても、モジュールファイルをロードしてからアンロードすることができます

そのため、スクリプトで実行する方が賢明です

後者を達成するために私は考えることができます:

  1. インタラクティブシェル を使用するには、現在のシェルの特定の履歴を無視して、スクリプトのShebangを次のように変更します。

    #!/bin/bash -i
    

    対話型シェルは、tty上のユーザー入力からコマンドを読み取ります。とりわけ、そのようなシェルはアクティベーション時にスタートアップファイルを読み取り、プロンプトを表示し、デフォルトでジョブ制御を有効にします...

  2. 代わりに、現在のシェルの特定のストーリーを継承したい場合は、それを入手することを試みることができます...しかし、サブシェル

    ( source runit.sh )
    
  3. type moduleを使用してmoduleの現在のエイリアス/関数を見つけ、スクリプトを変更します。一部の環境変数はmoduleに設定できないことに注意してください。
    必要に応じて、初期化スクリプトをディレクトリ$MODULESHOME/init/<Shell>に見つけることができます。


コメント
モジュールのQ&A で覚えているように

子プロセス(スクリプト)は、親プロセス環境を変更できません。スクリプトでのモジュールのロードは、スクリプト自体の環境にのみ影響します。 現在の環境でスクリプトを変更できる唯一の方法は、スクリプトを現在のプロセスに読み込むスクリプトを読み込むことです。

したがって、現在の環境の変更を避けたい場合は、Shebang(1)を変更するか、サブシェル(2)でスクリプトを取得することをお勧めします。ケースの使いやすさは完全にはわかりません(3)。



モジュールのマニュアルおよび説明ページからの抜粋

moduleは、モジュールパッケージへのユーザーインターフェイスです。 moduleエイリアスまたは関数modulecmdプログラムを実行し、シェルにコマンドの出力を評価させます。 modulecmdの最初の引数は、シェルのタイプを指定します。

Modulesパッケージとmoduleコマンドは、シェル固有の初期化スクリプトがシェルに読み込まれると初期化されます。スクリプトは、エイリアスまたはシェル関数としてモジュールコマンドを作成し、モジュール環境変数を作成します

4
Hastur