環境變量管理程序bmod使用教程

註:bmod屬於李雲海博士原創開發程序,版權屬於他,歡迎大家關注他的相關網站:

https://gitee.com/yhli/misc/tree/master/bmod

https://github.com/yhli1016/misc/tree/master/bmod

http://blog.sciencenet.cn/blog-2909108-1267515.html

1. 簡介

在UNIX/Linux系統下做計算,不可避免地會接觸到各種環境變量。編譯程序時,需要通過環境變量指定編譯器、編譯選項和依賴庫的位置。運行程序時,需要通過環境變量來查找可執行文件和動態連結庫。若設置不當,便會導致各種錯誤(詳見附錄)。因此管理環境變量便成了一件既重要又棘手的事。

最簡單的管理環境變量的方法就是直接在$HOME/.bashrc中添加相應設置。這種方法的缺點也是很明顯的:環境變量名易寫錯,添加或刪除設置後要重新登錄才能起效,bashrc冗長等等。大型超算中心通常用Environment Modules系統解決這個問題。但目前主流的Environment Modules系統安裝和使用都比較複雜,學習成本較高。而個人電腦、自己組裝的工作站和小型集群軟體環境簡單,再用Environment Modules系統牛刀殺雞之嫌。因此,在這里提供一個環境變量管理程序bmod。程序非常簡單,全部由bash語言寫成,主體僅有150行左右,但實現了一個Environment Modules系統最基本的功能。下面介紹安裝和使用方法。

2. 安裝

https://github.com/yhli1016/misc/tree/master/bmod

解壓後將bmod目錄移動到安裝路徑下面(本文中為$HOME/soft),打開init.sh,找到這兩行:

# Set up environment variables used by bmodexport BMOD_ROOT=$HOME/soft/bmod

將BMOD_ROOT設置為init.sh所在的目錄(在本文中為$HOME/soft/bmod),接著打開$HOME/.bashrc,添加如下設置:

source $HOME/soft/bmod/init.sh

最後執行命令source $HOME/.bashrc,安裝完成。modules目錄下面自帶了很多例子,在添加自己的腳本之前,記得全部刪除。

3. 使用

3.1 通過命令行添加和移除設置

3.1.1 使用預定義的環境變量

與程序編譯和運行相關的環境變量眾多,不僅難記,還容易拼錯。因此,bmod中預定義了常見的環境變量。以安裝在$HOME/soft/lib/fftw-3.3.8下面的fftw庫為例,為使該庫能正常工作,我們需要手動輸入如下命令:

fftw_root=$HOME/soft/lib/fftw-3.3.8export PATH=$fftw_root/bin:$PATHexport LIBRARY_PATH=$fftw_root/lib64:$LIBRARY_PATHexport LD_RUN_PATH=$fftw_root/lib64:$LD_RUN_PATHexport LD_LIBRARY_PATH=$fftw_root/lib64:$LD_LIBRARY_PATHexport C_INCLUDE_PATH=$fftw_root/include:$C_INCLUDE_PATHexport CPLUS_INCLUDE_PATH=$fftw_root/include:$CPLUS_INCLUDE_PATHunset fftw_root

而在bmod中,上述設置只需一行命令即可:

set_mod add pkg $HOME/soft/lib/fftw-3.3.8

移除設置只需運行下面命令:

set_mod rm pkg $HOME/soft/lib/fftw-3.3.8

set_mod命令後面參數含義:

第一個參數為add或rm,指定添加還是刪除設置;

第二個參數為預定義的環境變量類型;

第三個參數為添加到環境變量中,或從環境變量中刪除的設置。當預定義類型為pkg時,第三個參數無需具體到bin、lib64或include等子目錄,bmod會自動搜索和添加

目前bmod中預定義的類型和對應的環境變量為:

  • bin

    • PATH

  • lib:

    • LIBRARY_PATH

    • LD_RUN_PATH

    • LD_LIBRARY_PATH

  • inc

    • C_INCLUDE_PATH

    • CPLUS_INCLUDE_PATH

  • py

    • PYTHONPATH

  • pkg

    • PATH

    • LIBRARY_PATH

    • LD_RUN_PATH

    • LD_LIBRARY_PATH

    • C_INCLUDE_PATH

    • CPLUS_INCLUDE_PATH

當預定義類型為bin、lib、inc、py時,bmod不會自動搜索子目錄,所以第三個參數必須具體到bin、lib64或include。上面fftw的例子若用bin、lib、inc等預定義類型改寫,對應的命令為:

set_mod add bin $HOME/soft/lib/fftw-3.3.8/binset_mod add lib $HOME/soft/lib/fftw-3.3.8/lib64set_mod add inc $HOME/soft/lib/fftw-3.3.8/include

再看一個xcrysden的例子。程序安裝在$HOME/soft/dft/xcrysden-1.6.2-bin-shared,可執行文件為xcrysden,還有一個動態連結庫libTogl.so.2。為使這個程序正常運行,需將$HOME/soft/dft/xcrysden-1.6.2-bin-shared添加到環境變量PATH和LD_LIBRARY_PATH,對應操作為:

set_mod add bin $HOME/soft/dft/xcrysden-1.6.2-bin-sharedset_mod add lib $HOME/soft/dft/xcrysden-1.6.2-bin-shared

或者簡寫為set_mod add bin+lib $HOME/soft/dft/xcrysden-1.6.2-bin-shared。

3.1.2 使用自定義的環境變量

預定義的環境變量可以滿足大多數情形。若待修改的環境變量沒有預定義,可以用set_env和reset_env命令修改。

假設我們要把$HOME/soft/lib/abc/def添加到環境變量TEST中,對應操作為

set_env add TEST $HOME/soft/lib/abc/def

刪除時為

set_env rm TEST $HOME/soft/lib/abc/def

如果我們希望把環境變量重設為一個新的值,而不是把新的值追加到變量中,可以用reset_env命令。例如,要將openmp線程數設置為4,可以輸入:

reset_env add OMP_NUM_THREADS 4

若要將其恢復默認值,可以輸入:

reset_env rm OMP_NUM_THREADS

3.2 通過腳本添加和移除設置

一般來說,程序在編譯和運行過程中會涉及很多庫,需要我們輸入很多次set_mod和set_env命令。以siesta為例,加載設置時我們需要輸入:

siesta=$HOME/soft/dft/siesta-v4.1-b4set_mod add pkg $siesta/Docs/build/flook/0.8.1set_mod add pkg $siesta/Docs/build/hdf5/1.8.21set_mod add pkg $siesta/Docs/build/netcdf/4.7.4set_mod add pkg $siesta/Docs/build/zlib/1.2.11set_mod add bin $siesta/Objunset siestareset_env add OMP_NUM_THREADS 1

移除設置時需要輸入:

siesta=$HOME/soft/dft/siesta-v4.1-b4set_mod rm pkg $siesta/Docs/build/flook/0.8.1set_mod rm pkg $siesta/Docs/build/hdf5/1.8.21set_mod rm pkg $siesta/Docs/build/netcdf/4.7.4set_mod rm pkg $siesta/Docs/build/zlib/1.2.11set_mod rm bin $siesta/Objunset siestareset_env rm OMP_NUM_THREADS 1

而這些命令的區別,僅僅是把add換成了rm。這樣太麻煩了。在bmod中我們可以通過腳本,用同一套命令完成加載和卸載兩種操作。我們在$HOME/soft/bmod/modules下面新建一個bash腳本siesta-v4.1-b4.sh,把上面的命令存進去,並把add或rm換成$1:

siesta=$HOME/soft/dft/siesta-v4.1-b4set_mod $1 pkg $siesta/Docs/build/flook/0.8.1set_mod $1 pkg $siesta/Docs/build/hdf5/1.8.21set_mod $1 pkg $siesta/Docs/build/netcdf/4.7.4set_mod $1 pkg $siesta/Docs/build/zlib/1.2.11set_mod $1 bin $siesta/Objunset siestareset_env $1 OMP_NUM_THREADS 1

加載設置時輸入:

bmod add siesta-v4.1-b4

卸載時輸入:

bmod rm siesta-v4.1-b4

bmod會自動把$1替換成add或rm。需注意,如果系統中安裝了某個庫的多個版本,而待運行的程序只能使用特定版本,那麼在加載該版本前必須把其它版本卸掉。假設系統中還安裝了hdf5-1.10.12,上述設置就要改成:

set_mod rm pkg $HOME/soft/lib/hdf5-1.10.12siesta=$HOME/soft/dft/siesta-v4.1-b4set_mod $1 pkg $siesta/Docs/build/flook/0.8.1set_mod $1 pkg $siesta/Docs/build/hdf5/1.8.21set_mod $1 pkg $siesta/Docs/build/netcdf/4.7.4set_mod $1 pkg $siesta/Docs/build/zlib/1.2.11set_mod $1 bin $siesta/Objunset siestareset_env $1 OMP_NUM_THREADS 1

由於我們希望在加載hdf5-1.8.21之前卸載hdf5-1.10.12,所以set_mod後面的參數必須是rm,不能用$1代替。

除了add/rm外,bmod命令支持如下選項:

  • av: 列出所有可用腳本

  • ls: 列出所有已加載腳本

  • cl: 卸載已加載的腳本

  • pg: 卸載所有腳本(含未加載)

modules目錄下面中自帶了很多用作例子的腳本。下面是bmod av命令的輸出結果:

[yhli@linux-h149 ~]$ bmod av---- /home/yhli/soft/bmod/modules ---- 1) bgw-2.1 2) boost-1.75.0 3) fleurMaXR3.1 4) office 5) openmpi-4.0.5 6) qe-6.6 7) siesta-v4.1-b4 8) spex05.00 9) vasp.5.4.4 10) vesta 11) vtst 12) wannier90-2.1.0 13) xcrysden-1.6.2

以及bmod ls命令的輸出結果:

[yhli@linux-h149 ~]$ bmod lsCurrently loaded modules:

由於在一開始我們沒有加載任何腳本,所以bmod ls輸出為空。我們先用bmod add命令加載幾個腳本後,再來看有何不同:

[yhli@linux-h149 ~]$ bmod add bgw-2.1 boost vesta[yhli@linux-h149 ~]$ bmod lsCurrently loaded modules: 1) bgw-2.1 2) boost-1.75.0 3) vesta

可以看到這幾個腳本已被加載了。如果腳本名字中的版本號和主體以-隔開,可以省略不寫。所以bmod add boost是可以的,而bmod add vasp卻不行,必須輸入全稱bmod add vasp.5.4.4。

我們用bmod cl命令卸載已加載的腳本,看下效果:

[yhli@linux-h149 ~]$ bmod lsCurrently loaded modules:

可見所有已加載的腳本都已被卸載。bmod pg有類似效果,就不再展示了。

4. 補充說明

4.1 常見環境變量及報錯信息

4.1.1 PATH

系統需要通過這個環境變量查找可執行程序(二進位文件或腳本)。若未正確設置,會報類似如下錯誤:

[yhli@linux-h149 ~]$ pw.x-bash: pw.x: command not found

4.1.2 LD_RUN_PATH, LIBRARY_PATH

這兩個環境變量指定編譯程序時,所用到的庫文件所在位置。庫文件有兩種:靜態連結庫(libxxx.a)和動態連結庫(libxxx.so)。若未正確設置,會報類似如下錯誤:

/usr/lib64/gcc/x86_64-suse-linux/7/../../../../x86_64-suse-linux/bin/ld: cannot find -lboost_python38collect2: error: ld returned 1 exit statusmake: *** [Makefile:65:pyxaid_core.so] Error 1

4.1.3 LD_LIBRARY_PATH

這個環境變量指定運行程序時,所用到的動態連結庫所在位置。若未正確設置,會報類似如下錯誤:

[yhli@linux-h149 doublecmd]$ ./doublecmd./doublecmd: error while loading shared libraries: libQt5Pas.so.1: cannot open shared object file: No such file or directory

4.1.4 C_INCLUDE_PATH, CPLUS_INCLUDE_PATH

這兩個環境變量指定編譯程序時,所用到的頭文件所在位置。若未正確設置,會報類似如下錯誤:

pyxaid_core.cpp:10:10: fatal error: boost/python.hpp: No such file or directory#include <boost/python.hpp> ^~~~~~~~~~~~~~~~~~compilation terminated.make: *** [Makefile:59:pyxaid_core.o] Error 1

4.2 注意事項

目前bmod缺失對已加載模塊檢查的功能。以下述命令為例:

[yhli@linux-h149 ~]$ bmod add qe[yhli@linux-h149 ~]$ bmod add fleurMaXR3.1[yhli@linux-h149 ~]$ bmod lsCurrently loaded modules: 1) qe-6.6 2) fleurMaXR3.

當執行第一條命令bmod add qe時,bmod加載了與qe相關的設置。一般來說,這需要卸載衝突庫和加載依賴庫。當執行第二條命令bmod add fleurMaXR3.1時,bmod同樣會執行類似操作。但是,如果fleur依賴的某個庫恰巧與qe衝突,或者與fleur有衝突的某個庫恰巧是qe的依賴庫,那麼執行完第二句後,qe的環境變量就被破壞了。也就是說,bmod目前只能「狗熊掰玉米」,保證最後一個加載的程序可用。要解決這個問題,需要複雜的依賴和衝突關係分析。這已經超出了bmod的設計初衷,如有這方面的需求,可以選擇功能更強大的Environment Modules系統,或本人開發的Pmod 。

來源:kknews環境變量管理程序bmod使用教程