linux下的环境变量,可以通过几个地方来控制 :1、系统级的环境变量 ,通过/etc/profile文件来修改;2、用户级的环境变量,通过$HOME/.profile来修改,如果是bash,也可以根据.bashrc文件来修改,如果是csh,也可以根据.cshrc文件来修改;3、命令级的环境变量设置,通过直接在窗口敲入命令来设置环境变量,这个设置的环境变量不是永久生效的,是临时的环境变量,当窗口关闭的时候,环境变量也随着失效。下面来聊一下这几个环境变量的优先级。你可以以下方式进行测试。在/etc/profile $HOME/.profile $HOME/.bashrc 和使用命令行,来分别设置一个环境变量,分别如下:
sudo vi /etc/profile export MENG=3
vi .profile export MENG=2
vi .bashrc export MENG=1
然后关闭窗口,重新打开(为了让环境变量生效),输入
export MENG=0
echo $MENG
结果是0,说明这四个里面,使用命令行的方式来设置环境变量,优先级最高,那谁是第二,你可以直接把窗口关闭,在重现打开,直接输入
echo $MENG
结果是1,说明如果不使用命令行的方式,.bashrc文件或者是.cshrc配置的优先级比较高。我们接着测试下一个,把.bashrc文件中export注释掉,退出,重新开启一个窗口,再输入一次echo,结果是没有任何的记录,.profile没有生效,我注销了当前用户,重新登录进来,在执行echo $MENG结果出来了是2,这种方式不建议使用,因为生产上不能使用这种方式。一般服务器,不会允许这种操作,我们看最后一种方式,把.profile里面的内容注释掉,也是需要重启才能够生效。所以不推荐使用后两种方式。
下面介绍两个常用的环境变量的含义:
1、PATH,系统可执行文件查找的路径
2、LD_LIBRARY_PATH 系统动态库查找的路径
这两个环境变量在定位问题的过程中使用非常广泛,比如说,你在path下配置了两个路径A和B,而路径A和B路径下都有一个相同的可执行文件test,那你不知道,现在到底执行的是那个可执行文件,这个时候就要看path的配置了,你可以使用which test命令,来查看test到底使用的是A路劲还是B路径。如果想调整先用A或者先用B,就需要修改path,而LD_LIBRARY_PATH是程序依赖的动态库的路径,查看依赖的动态,在linux下可以使用 ldd 命令,通过ldd,可以看到使用的动态库是那个路径下。
.bashrc文件中,除了可以使用export命令,来设置环境变量,还可以使用alias命令,来对你的shell命令来取别名,例如:
alias h history alias sc source ~/.cshrc alias cdsrc cd $OB_SRC alias cdrel cd $OB_REL alias cdrun cd $OB_RUN alias gm gmake
通过alias,可以算是新增了一条shell命令,这种情况,在你要进入一个比较深的目录层级的是,使用非常方便,比如说,你可以把这个很深层级的目录路径保存为一个环境变量,比如上面个的OB_SRC,可以是/a/bc/c/d/e/f/g/g/h/i,如果要进入这个目录,你要cd很多次,如果使用alias+环境变量的方式,直接一个cdsrc命令即可到达。这个是另外一个用法,关于环境变量的内容使用十分丰富,环境变量也可以作为宏定义,来作为C++的编译宏。
代码如下:
#include<iostream> #include<string> #include<set> using namespace std; /** * 重载<< 用于输出 */ template<class Data> inline ostream& operator<<(ostream& str, const set<Data>& data) { str << "{\n\t"; typedef typename set<Data>::const_iterator ConstIterator; for(ConstIterator iter = data.begin(); iter != data.end(); ++iter) { ConstIterator iterTmp = iter; iterTmp++; if(iterTmp == data.end()) { str << *iter << "\n"; } else { str << *iter << "\n\t"; } } return str << "}"; } /** * 测试类 */ class CTest { public: CTest(){} ~CTest(){} bool operator <(const CTest& cTest) const { #ifdef POS return m_iSize < cTest.get_size(); #endif return m_iSize > cTest.get_size(); } public: inline int get_size() const { return m_iSize; } inline void set_size(const int & iSize) { m_iSize = iSize; } private: int m_iSize; }; /** * 重载<< 用于输出 */ inline ostream& operator<<(ostream& str, const CTest& data) { return str << "[size = " << data.get_size() << "]"; } int main(int args,char* argvs[]) { // set<string> setStr; // setStr.insert("ab"); // setStr.insert("1"); // setStr.insert("2"); // setStr.insert("abc"); // setStr.insert("aba"); set<CTest> setClass; CTest cTest1; CTest cTest2; cTest1.set_size(1); cTest2.set_size(2); setClass.insert(cTest1); setClass.insert(cTest2); // set<int> setInt; // setInt.insert(1); // setInt.insert(2); // setInt.insert(2); // cout << setStr << endl; cout << setClass << endl; // cout << setInt << endl; }
这个里面,有一个POS的宏定义,编译的时候,有没有POS的宏定义,编译运行的结果是不一样的,对于输出的结果是不一样的
我们先看看直接编译的结果:
mengpl@ubuntu:~/workspace/basic$ g++ testset.cpp -o testset -g mengpl@ubuntu:~/workspace/basic$ ./testset { [size = 2] [size = 1] }
此时,输出是反序的。我们可以在编译的时候,加上一个POS的宏,编译命令和输出结果变为:
mengpl@ubuntu:~/workspace/basic$ g++ testset.cpp -DPOS -o testset -g mengpl@ubuntu:~/workspace/basic$ ./testset { [size = 1] [size = 2] }
可以这样,就不够灵活了,这个宏,有些机器上是需要的,有些机器上是不需要的,这个就比较难办,我举一个实际的例子,像电信行业,都是一个省份一个项目,但是我们的代码是需要同一套的,有时候,两个省份需要的动能是不一样的,这个时候,就需要使用的宏定义,给这个省份编译这部分代码,给另一个省份编译另一份代码,而代码又是同一套,如何支持,这个时候,可以使用环境变量,把宏定义,作为环境变量的值。针对这个例子来说,可以这样使用:
mengpl@ubuntu:~/workspace/basic$ export SEQ=POS mengpl@ubuntu:~/workspace/basic$ g++ testset.cpp -D$SEQ -o testset -g mengpl@ubuntu:~/workspace/basic$ ./testset { [size = 1] [size = 2] }
增加一个SEQ的环境变量,设置到不同的主机,就能达到,不同的主机,编译不同的代码了。